summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/arm64/iort.c111
-rw-r--r--drivers/acpi/nfit/core.c679
-rw-r--r--drivers/acpi/nfit/mce.c5
-rw-r--r--drivers/acpi/nfit/nfit.h22
-rw-r--r--drivers/acpi/processor_perflib.c11
-rw-r--r--drivers/base/memory.c7
-rw-r--r--drivers/block/rbd.c2452
-rw-r--r--drivers/char/rtc.c83
-rw-r--r--drivers/cpufreq/armada-37xx-cpufreq.c2
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c15
-rw-r--r--drivers/cpufreq/freq_table.c14
-rw-r--r--drivers/cpufreq/intel_pstate.c1
-rw-r--r--drivers/cpufreq/scmi-cpufreq.c10
-rw-r--r--drivers/cpufreq/ti-cpufreq.c2
-rw-r--r--drivers/cpuidle/cpuidle.c10
-rw-r--r--drivers/cpuidle/governors/ladder.c3
-rw-r--r--drivers/cpuidle/governors/menu.c113
-rw-r--r--drivers/dax/Kconfig5
-rw-r--r--drivers/dax/device.c38
-rw-r--r--drivers/dax/pmem.c18
-rw-r--r--drivers/dax/super.c15
-rw-r--r--drivers/dma/Kconfig12
-rw-r--r--drivers/dma/Makefile2
-rw-r--r--drivers/dma/at_xdmac.c4
-rw-r--r--drivers/dma/dmatest.c16
-rw-r--r--drivers/dma/dw-axi-dmac/Makefile1
-rw-r--r--drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c1008
-rw-r--r--drivers/dma/dw-axi-dmac/dw-axi-dmac.h334
-rw-r--r--drivers/dma/edma.c6
-rw-r--r--drivers/dma/imx-sdma.c21
-rw-r--r--drivers/dma/mediatek/Kconfig13
-rw-r--r--drivers/dma/mediatek/Makefile1
-rw-r--r--drivers/dma/mediatek/mtk-hsdma.c1056
-rw-r--r--drivers/dma/pl330.c6
-rw-r--r--drivers/dma/qcom/bam_dma.c59
-rw-r--r--drivers/dma/sh/rcar-dmac.c13
-rw-r--r--drivers/dma/stm32-dma.c287
-rw-r--r--drivers/firmware/broadcom/Kconfig1
-rw-r--r--drivers/firmware/broadcom/bcm47xx_sprom.c18
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c4
-rw-r--r--drivers/hwmon/Kconfig5
-rw-r--r--drivers/hwmon/g762.c53
-rw-r--r--drivers/hwmon/lm92.c63
-rw-r--r--drivers/hwmon/nct6775.c231
-rw-r--r--drivers/hwmon/pmbus/Kconfig4
-rw-r--r--drivers/hwmon/pmbus/adm1275.c71
-rw-r--r--drivers/hwmon/pmbus/max8688.c2
-rw-r--r--drivers/hwmon/pmbus/ucd9000.c350
-rw-r--r--drivers/hwmon/sht21.c3
-rw-r--r--drivers/hwmon/via-cputemp.c31
-rw-r--r--drivers/iommu/amd_iommu.c320
-rw-r--r--drivers/iommu/amd_iommu_init.c2
-rw-r--r--drivers/iommu/amd_iommu_types.h6
-rw-r--r--drivers/iommu/arm-smmu-v3.c542
-rw-r--r--drivers/iommu/dma-iommu.c8
-rw-r--r--drivers/iommu/dmar.c2
-rw-r--r--drivers/iommu/exynos-iommu.c13
-rw-r--r--drivers/iommu/intel-iommu.c6
-rw-r--r--drivers/iommu/intel-svm.c17
-rw-r--r--drivers/iommu/io-pgtable-arm-v7s.c21
-rw-r--r--drivers/iommu/io-pgtable-arm.c91
-rw-r--r--drivers/iommu/io-pgtable.h4
-rw-r--r--drivers/iommu/iommu.c6
-rw-r--r--drivers/iommu/mtk_iommu.c15
-rw-r--r--drivers/iommu/mtk_iommu.h1
-rw-r--r--drivers/iommu/mtk_iommu_v1.c54
-rw-r--r--drivers/iommu/omap-iommu.c2
-rw-r--r--drivers/iommu/rockchip-iommu.c592
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c3
-rw-r--r--drivers/md/Kconfig2
-rw-r--r--drivers/md/dm-linear.c6
-rw-r--r--drivers/md/dm-log-writes.c95
-rw-r--r--drivers/md/dm-stripe.c6
-rw-r--r--drivers/md/dm.c10
-rw-r--r--drivers/media/cec/cec-pin.c6
-rw-r--r--drivers/media/common/v4l2-tpg/v4l2-tpg-core.c2
-rw-r--r--drivers/media/dvb-core/dvb_frontend.c2
-rw-r--r--drivers/media/i2c/adv748x/adv748x-afe.c3
-rw-r--r--drivers/media/i2c/dw9714.c14
-rw-r--r--drivers/media/i2c/imx274.c2
-rw-r--r--drivers/media/i2c/ov13858.c19
-rw-r--r--drivers/media/i2c/ov2685.c1
-rw-r--r--drivers/media/i2c/ov5640.c38
-rw-r--r--drivers/media/i2c/ov5645.c29
-rw-r--r--drivers/media/i2c/ov5670.c19
-rw-r--r--drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c4
-rw-r--r--drivers/media/platform/qcom/venus/firmware.c2
-rw-r--r--drivers/media/platform/qcom/venus/vdec.c13
-rw-r--r--drivers/media/platform/qcom/venus/venc.c13
-rw-r--r--drivers/media/platform/vivid/vivid-vid-cap.c5
-rw-r--r--drivers/media/platform/vsp1/vsp1_wpf.c2
-rw-r--r--drivers/media/tuners/r820t.c4
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-dvb.c2
-rw-r--r--drivers/media/usb/gspca/Kconfig2
-rw-r--r--drivers/media/v4l2-core/v4l2-compat-ioctl32.c4
-rw-r--r--drivers/media/v4l2-core/v4l2-dev.c8
-rw-r--r--drivers/misc/kgdbts.c8
-rw-r--r--drivers/mmc/core/block.c1
-rw-r--r--drivers/mmc/host/jz4740_mmc.c2
-rw-r--r--drivers/mmc/host/tmio_mmc_core.c2
-rw-r--r--drivers/mtd/ubi/block.c2
-rw-r--r--drivers/mtd/ubi/build.c11
-rw-r--r--drivers/mtd/ubi/fastmap-wl.c1
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c2
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c2
-rw-r--r--drivers/nvdimm/Kconfig13
-rw-r--r--drivers/nvdimm/Makefile1
-rw-r--r--drivers/nvdimm/btt_devs.c21
-rw-r--r--drivers/nvdimm/bus.c14
-rw-r--r--drivers/nvdimm/claim.c2
-rw-r--r--drivers/nvdimm/core.c6
-rw-r--r--drivers/nvdimm/dax_devs.c5
-rw-r--r--drivers/nvdimm/dimm.c8
-rw-r--r--drivers/nvdimm/dimm_devs.c7
-rw-r--r--drivers/nvdimm/label.c85
-rw-r--r--drivers/nvdimm/label.h2
-rw-r--r--drivers/nvdimm/namespace_devs.c42
-rw-r--r--drivers/nvdimm/nd.h1
-rw-r--r--drivers/nvdimm/of_pmem.c119
-rw-r--r--drivers/nvdimm/pfn_devs.c25
-rw-r--r--drivers/nvdimm/pmem.c14
-rw-r--r--drivers/nvdimm/region.c4
-rw-r--r--drivers/nvdimm/region_devs.c9
-rw-r--r--drivers/of/unittest.c2
-rw-r--r--drivers/platform/mellanox/mlxreg-hotplug.c31
-rw-r--r--drivers/platform/x86/Kconfig3
-rw-r--r--drivers/platform/x86/dell-smbios-base.c4
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c199
-rw-r--r--drivers/platform/x86/gpd-pocket-fan.c4
-rw-r--r--drivers/platform/x86/intel-hid.c14
-rw-r--r--drivers/platform/x86/intel_turbo_max_3.c3
-rw-r--r--drivers/platform/x86/mlx-platform.c68
-rw-r--r--drivers/platform/x86/silead_dmi.c17
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c8
-rw-r--r--drivers/platform/x86/topstar-laptop.c363
-rw-r--r--drivers/platform/x86/wmi.c23
-rw-r--r--drivers/rapidio/devices/rio_mport_cdev.c122
-rw-r--r--drivers/rapidio/rio-scan.c6
-rw-r--r--drivers/remoteproc/Kconfig19
-rw-r--r--drivers/remoteproc/Makefile1
-rw-r--r--drivers/remoteproc/imx_rproc.c23
-rw-r--r--drivers/remoteproc/qcom_adsp_pil.c20
-rw-r--r--drivers/remoteproc/qcom_common.c56
-rw-r--r--drivers/remoteproc/qcom_common.h23
-rw-r--r--drivers/remoteproc/qcom_q6v5_pil.c9
-rw-r--r--drivers/remoteproc/qcom_sysmon.c579
-rw-r--r--drivers/remoteproc/qcom_wcnss.c11
-rw-r--r--drivers/remoteproc/remoteproc_core.c152
-rw-r--r--drivers/remoteproc/remoteproc_internal.h7
-rw-r--r--drivers/rpmsg/qcom_glink_native.c18
-rw-r--r--drivers/rpmsg/qcom_glink_smem.c3
-rw-r--r--drivers/rpmsg/qcom_smd.c51
-rw-r--r--drivers/rpmsg/rpmsg_core.c2
-rw-r--r--drivers/rtc/Kconfig13
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/class.c77
-rw-r--r--drivers/rtc/hctosys.c5
-rw-r--r--drivers/rtc/interface.c107
-rw-r--r--drivers/rtc/nvmem.c29
-rw-r--r--drivers/rtc/rtc-88pm80x.c4
-rw-r--r--drivers/rtc/rtc-88pm860x.c4
-rw-r--r--drivers/rtc/rtc-ab-b5ze-s3.c4
-rw-r--r--drivers/rtc/rtc-ab3100.c2
-rw-r--r--drivers/rtc/rtc-ab8500.c57
-rw-r--r--drivers/rtc/rtc-abx80x.c6
-rw-r--r--drivers/rtc/rtc-ac100.c26
-rw-r--r--drivers/rtc/rtc-at91sam9.c1
-rw-r--r--drivers/rtc/rtc-au1xxx.c2
-rw-r--r--drivers/rtc/rtc-bq32k.c8
-rw-r--r--drivers/rtc/rtc-brcmstb-waketimer.c3
-rw-r--r--drivers/rtc/rtc-cmos.c87
-rw-r--r--drivers/rtc/rtc-coh901331.c2
-rw-r--r--drivers/rtc/rtc-core.h8
-rw-r--r--drivers/rtc/rtc-cpcap.c2
-rw-r--r--drivers/rtc/rtc-cros-ec.c8
-rw-r--r--drivers/rtc/rtc-da9052.c3
-rw-r--r--drivers/rtc/rtc-da9055.c2
-rw-r--r--drivers/rtc/rtc-da9063.c2
-rw-r--r--drivers/rtc/rtc-ds1216.c2
-rw-r--r--drivers/rtc/rtc-ds1286.c2
-rw-r--r--drivers/rtc/rtc-ds1302.c7
-rw-r--r--drivers/rtc/rtc-ds1305.c24
-rw-r--r--drivers/rtc/rtc-ds1307.c32
-rw-r--r--drivers/rtc/rtc-ds1343.c185
-rw-r--r--drivers/rtc/rtc-ds1347.c2
-rw-r--r--drivers/rtc/rtc-ds1390.c2
-rw-r--r--drivers/rtc/rtc-ds1511.c26
-rw-r--r--drivers/rtc/rtc-ds1553.c78
-rw-r--r--drivers/rtc/rtc-ds1685.c2
-rw-r--r--drivers/rtc/rtc-ds1742.c75
-rw-r--r--drivers/rtc/rtc-ds2404.c2
-rw-r--r--drivers/rtc/rtc-ds3232.c2
-rw-r--r--drivers/rtc/rtc-efi.c2
-rw-r--r--drivers/rtc/rtc-fm3130.c3
-rw-r--r--drivers/rtc/rtc-goldfish.c2
-rw-r--r--drivers/rtc/rtc-isl12022.c20
-rw-r--r--drivers/rtc/rtc-isl12026.c501
-rw-r--r--drivers/rtc/rtc-isl1208.c47
-rw-r--r--drivers/rtc/rtc-jz4740.c2
-rw-r--r--drivers/rtc/rtc-lib.c8
-rw-r--r--drivers/rtc/rtc-lpc24xx.c2
-rw-r--r--drivers/rtc/rtc-lpc32xx.c2
-rw-r--r--drivers/rtc/rtc-ls1x.c2
-rw-r--r--drivers/rtc/rtc-m41t80.c42
-rw-r--r--drivers/rtc/rtc-m41t93.c2
-rw-r--r--drivers/rtc/rtc-m41t94.c3
-rw-r--r--drivers/rtc/rtc-m48t35.c2
-rw-r--r--drivers/rtc/rtc-m48t59.c61
-rw-r--r--drivers/rtc/rtc-m48t86.c25
-rw-r--r--drivers/rtc/rtc-max6900.c19
-rw-r--r--drivers/rtc/rtc-max6902.c2
-rw-r--r--drivers/rtc/rtc-max6916.c2
-rw-r--r--drivers/rtc/rtc-max77686.c4
-rw-r--r--drivers/rtc/rtc-max8997.c2
-rw-r--r--drivers/rtc/rtc-max8998.c2
-rw-r--r--drivers/rtc/rtc-mc13xxx.c2
-rw-r--r--drivers/rtc/rtc-mcp795.c4
-rw-r--r--drivers/rtc/rtc-mpc5121.c2
-rw-r--r--drivers/rtc/rtc-mrst.c4
-rw-r--r--drivers/rtc/rtc-msm6242.c2
-rw-r--r--drivers/rtc/rtc-mt7622.c3
-rw-r--r--drivers/rtc/rtc-mv.c14
-rw-r--r--drivers/rtc/rtc-mxc_v2.c2
-rw-r--r--drivers/rtc/rtc-nuc900.c14
-rw-r--r--drivers/rtc/rtc-omap.c6
-rw-r--r--drivers/rtc/rtc-pcap.c2
-rw-r--r--drivers/rtc/rtc-pcf2123.c2
-rw-r--r--drivers/rtc/rtc-pcf2127.c2
-rw-r--r--drivers/rtc/rtc-pcf50633.c2
-rw-r--r--drivers/rtc/rtc-pcf85063.c20
-rw-r--r--drivers/rtc/rtc-pcf8523.c2
-rw-r--r--drivers/rtc/rtc-pcf85363.c205
-rw-r--r--drivers/rtc/rtc-pic32.c2
-rw-r--r--drivers/rtc/rtc-pm8xxx.c55
-rw-r--r--drivers/rtc/rtc-ps3.c2
-rw-r--r--drivers/rtc/rtc-r7301.c2
-rw-r--r--drivers/rtc/rtc-r9701.c2
-rw-r--r--drivers/rtc/rtc-rk808.c25
-rw-r--r--drivers/rtc/rtc-rp5c01.c67
-rw-r--r--drivers/rtc/rtc-rs5c348.c5
-rw-r--r--drivers/rtc/rtc-rs5c372.c24
-rw-r--r--drivers/rtc/rtc-rv8803.c33
-rw-r--r--drivers/rtc/rtc-rx4581.c6
-rw-r--r--drivers/rtc/rtc-rx6110.c2
-rw-r--r--drivers/rtc/rtc-rx8010.c2
-rw-r--r--drivers/rtc/rtc-rx8025.c2
-rw-r--r--drivers/rtc/rtc-rx8581.c6
-rw-r--r--drivers/rtc/rtc-s35390a.c38
-rw-r--r--drivers/rtc/rtc-s3c.c2
-rw-r--r--drivers/rtc/rtc-s5m.c27
-rw-r--r--drivers/rtc/rtc-sc27xx.c2
-rw-r--r--drivers/rtc/rtc-sh.c2
-rw-r--r--drivers/rtc/rtc-sirfsoc.c18
-rw-r--r--drivers/rtc/rtc-snvs.c15
-rw-r--r--drivers/rtc/rtc-spear.c12
-rw-r--r--drivers/rtc/rtc-st-lpc.c16
-rw-r--r--drivers/rtc/rtc-starfire.c2
-rw-r--r--drivers/rtc/rtc-stk17ta8.c74
-rw-r--r--drivers/rtc/rtc-sun6i.c2
-rw-r--r--drivers/rtc/rtc-sunxi.c2
-rw-r--r--drivers/rtc/rtc-sysfs.c12
-rw-r--r--drivers/rtc/rtc-tegra.c4
-rw-r--r--drivers/rtc/rtc-tps6586x.c2
-rw-r--r--drivers/rtc/rtc-tx4939.c95
-rw-r--r--drivers/rtc/rtc-wm831x.c2
-rw-r--r--drivers/rtc/rtc-xgene.c2
-rw-r--r--drivers/rtc/rtc-zynqmp.c2
-rw-r--r--drivers/rtc/systohc.c2
-rw-r--r--drivers/s390/block/Kconfig2
-rw-r--r--drivers/soc/qcom/Kconfig2
-rw-r--r--drivers/soc/qcom/mdt_loader.c7
-rw-r--r--drivers/staging/lustre/lustre/llite/glimpse.c2
-rw-r--r--drivers/staging/lustre/lustre/mdc/mdc_request.c8
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-gc0310.c2
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c25
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-ov2680.c18
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-ov2722.c18
-rw-r--r--drivers/staging/media/atomisp/i2c/gc0310.h3
-rw-r--r--drivers/staging/media/atomisp/i2c/ov2722.h2
-rw-r--r--drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c28
-rw-r--r--drivers/staging/media/atomisp/i2c/ov5693/ov5693.h2
-rw-r--r--drivers/staging/media/atomisp/include/linux/atomisp_platform.h4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/Makefile4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_cmd.c42
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_cmd.h2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat.h20
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c58
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.h3
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_drvfs.c1
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c14
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_ioctl.c10
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c14
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.h8
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/camera/util/interface/ia_css_util.h6
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/camera/util/src/util.c72
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/css_2401_csi2p_system/system_global.h4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/debug.c2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/gp_timer.c2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_formatter.c5
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system.c24
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system_local.h2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system_private.h4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/system_global.h4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/host/input_system_public.h14
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_input_port.h20
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_irq.h4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_metadata.h4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_mipi.h4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_stream_format.h71
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_stream_public.h8
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm.host.h1
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm_default.host.c71
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm_default.host.h22
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2.host.h1
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2_default.host.c26
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2_default.host.h23
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8.host.h1
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8_default.host.c94
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8_default.host.h22
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/output/output_1.0/ia_css_output.host.c2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/raw/raw_1.0/ia_css_raw.host.c42
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/raw/raw_1.0/ia_css_raw_types.h2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.c2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.h1
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf_default.host.c36
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf_default.host.h23
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/vf/vf_1.0/ia_css_vf.host.c10
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/interface/ia_css_binary.h8
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/src/binary.c6
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/bufq/src/bufq.c9
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/src/ia_css_debug.c111
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/ifmtr/src/ifmtr.c96
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/inputfifo/interface/ia_css_inputfifo.h6
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/inputfifo/src/inputfifo.c22
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/interface/ia_css_isys.h20
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/csi_rx_rmgr.c4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/isys_init.c4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/rx.c146
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/virtual_isys.c12
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/pipeline/src/pipeline.c6
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/rmgr/src/rmgr_vbuf.c8
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c194
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_mipi.c58
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_params.c9
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_sp.c25
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_sp.h2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_stream_format.c58
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_stream_format.h2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/include/mmu/isp_mmu.h4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/mmu/isp_mmu.c13
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/mmu/sh_mmu_mrfld.c16
-rw-r--r--drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c8
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_resizer.c4
-rw-r--r--drivers/staging/media/imx/imx-media-csi.c7
-rw-r--r--drivers/video/Kconfig3
-rw-r--r--drivers/video/console/sticore.c4
-rw-r--r--drivers/video/fbdev/Kconfig8
-rw-r--r--drivers/video/fbdev/amba-clcd.c3
-rw-r--r--drivers/video/fbdev/atmel_lcdfb.c31
-rw-r--r--drivers/video/fbdev/aty/aty128fb.c2
-rw-r--r--drivers/video/fbdev/aty/mach64_ct.c2
-rw-r--r--drivers/video/fbdev/aty/radeon_base.c21
-rw-r--r--drivers/video/fbdev/au1100fb.c9
-rw-r--r--drivers/video/fbdev/fsl-diu-fb.c6
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_crtc2.c5
-rw-r--r--drivers/video/fbdev/offb.c2
-rw-r--r--drivers/video/fbdev/s3c-fb.c168
-rw-r--r--drivers/video/fbdev/sis/init.h76
-rw-r--r--drivers/video/fbdev/sis/init301.c326
-rw-r--r--drivers/video/fbdev/sis/init301.h320
-rw-r--r--drivers/video/fbdev/sis/sis.h131
-rw-r--r--drivers/video/fbdev/sis/sis_main.c51
-rw-r--r--drivers/video/fbdev/sis/sis_main.h117
-rw-r--r--drivers/video/fbdev/smscufx.c59
-rw-r--r--drivers/video/fbdev/ssd1307fb.c3
-rw-r--r--drivers/video/fbdev/stifb.c6
-rw-r--r--drivers/video/fbdev/udlfb.c39
-rw-r--r--drivers/video/fbdev/vermilion/vermilion.c2
-rw-r--r--drivers/video/fbdev/via/via_aux_sii164.c2
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1631.c2
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1632.c2
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1636.c2
-rw-r--r--drivers/video/of_display_timing.c20
-rw-r--r--drivers/virtio/virtio_balloon.c6
-rw-r--r--drivers/xen/xen-acpi-processor.c30
-rw-r--r--drivers/xen/xenbus/xenbus_dev_frontend.c16
-rw-r--r--drivers/xen/xenbus/xenbus_xs.c4
387 files changed, 10608 insertions, 6732 deletions
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 9e702bc4960f..7a3a541046ed 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -34,6 +34,7 @@
struct iort_its_msi_chip {
struct list_head list;
struct fwnode_handle *fw_node;
+ phys_addr_t base_addr;
u32 translation_id;
};
@@ -156,14 +157,16 @@ static LIST_HEAD(iort_msi_chip_list);
static DEFINE_SPINLOCK(iort_msi_chip_lock);
/**
- * iort_register_domain_token() - register domain token and related ITS ID
- * to the list from where we can get it back later on.
+ * iort_register_domain_token() - register domain token along with related
+ * ITS ID and base address to the list from where we can get it back later on.
* @trans_id: ITS ID.
+ * @base: ITS base address.
* @fw_node: Domain token.
*
* Returns: 0 on success, -ENOMEM if no memory when allocating list element
*/
-int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node)
+int iort_register_domain_token(int trans_id, phys_addr_t base,
+ struct fwnode_handle *fw_node)
{
struct iort_its_msi_chip *its_msi_chip;
@@ -173,6 +176,7 @@ int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node)
its_msi_chip->fw_node = fw_node;
its_msi_chip->translation_id = trans_id;
+ its_msi_chip->base_addr = base;
spin_lock(&iort_msi_chip_lock);
list_add(&its_msi_chip->list, &iort_msi_chip_list);
@@ -569,6 +573,24 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id)
return -ENODEV;
}
+static int __maybe_unused iort_find_its_base(u32 its_id, phys_addr_t *base)
+{
+ struct iort_its_msi_chip *its_msi_chip;
+ int ret = -ENODEV;
+
+ spin_lock(&iort_msi_chip_lock);
+ list_for_each_entry(its_msi_chip, &iort_msi_chip_list, list) {
+ if (its_msi_chip->translation_id == its_id) {
+ *base = its_msi_chip->base_addr;
+ ret = 0;
+ break;
+ }
+ }
+ spin_unlock(&iort_msi_chip_lock);
+
+ return ret;
+}
+
/**
* iort_dev_find_its_id() - Find the ITS identifier for a device
* @dev: The device.
@@ -754,6 +776,24 @@ static inline bool iort_iommu_driver_enabled(u8 type)
}
#ifdef CONFIG_IOMMU_API
+static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
+{
+ struct acpi_iort_node *iommu;
+ struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+
+ iommu = iort_get_iort_node(fwspec->iommu_fwnode);
+
+ if (iommu && (iommu->type == ACPI_IORT_NODE_SMMU_V3)) {
+ struct acpi_iort_smmu_v3 *smmu;
+
+ smmu = (struct acpi_iort_smmu_v3 *)iommu->node_data;
+ if (smmu->model == ACPI_IORT_SMMU_V3_HISILICON_HI161X)
+ return iommu;
+ }
+
+ return NULL;
+}
+
static inline const struct iommu_ops *iort_fwspec_iommu_ops(
struct iommu_fwspec *fwspec)
{
@@ -770,6 +810,69 @@ static inline int iort_add_device_replay(const struct iommu_ops *ops,
return err;
}
+
+/**
+ * iort_iommu_msi_get_resv_regions - Reserved region driver helper
+ * @dev: Device from iommu_get_resv_regions()
+ * @head: Reserved region list from iommu_get_resv_regions()
+ *
+ * Returns: Number of msi reserved regions on success (0 if platform
+ * doesn't require the reservation or no associated msi regions),
+ * appropriate error value otherwise. The ITS interrupt translation
+ * spaces (ITS_base + SZ_64K, SZ_64K) associated with the device
+ * are the msi reserved regions.
+ */
+int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
+{
+ struct acpi_iort_its_group *its;
+ struct acpi_iort_node *iommu_node, *its_node = NULL;
+ int i, resv = 0;
+
+ iommu_node = iort_get_msi_resv_iommu(dev);
+ if (!iommu_node)
+ return 0;
+
+ /*
+ * Current logic to reserve ITS regions relies on HW topologies
+ * where a given PCI or named component maps its IDs to only one
+ * ITS group; if a PCI or named component can map its IDs to
+ * different ITS groups through IORT mappings this function has
+ * to be reworked to ensure we reserve regions for all ITS groups
+ * a given PCI or named component may map IDs to.
+ */
+
+ for (i = 0; i < dev->iommu_fwspec->num_ids; i++) {
+ its_node = iort_node_map_id(iommu_node,
+ dev->iommu_fwspec->ids[i],
+ NULL, IORT_MSI_TYPE);
+ if (its_node)
+ break;
+ }
+
+ if (!its_node)
+ return 0;
+
+ /* Move to ITS specific data */
+ its = (struct acpi_iort_its_group *)its_node->node_data;
+
+ for (i = 0; i < its->its_count; i++) {
+ phys_addr_t base;
+
+ if (!iort_find_its_base(its->identifiers[i], &base)) {
+ int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
+ struct iommu_resv_region *region;
+
+ region = iommu_alloc_resv_region(base + SZ_64K, SZ_64K,
+ prot, IOMMU_RESV_MSI);
+ if (region) {
+ list_add_tail(&region->list, head);
+ resv++;
+ }
+ }
+ }
+
+ return (resv == its->its_count) ? resv : -ENODEV;
+}
#else
static inline const struct iommu_ops *iort_fwspec_iommu_ops(
struct iommu_fwspec *fwspec)
@@ -777,6 +880,8 @@ static inline const struct iommu_ops *iort_fwspec_iommu_ops(
static inline int iort_add_device_replay(const struct iommu_ops *ops,
struct device *dev)
{ return 0; }
+int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
+{ return 0; }
#endif
static int iort_iommu_xlate(struct device *dev, struct acpi_iort_node *node,
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 22a112b4f4d8..e2235ed3e4be 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -36,16 +36,6 @@ static bool force_enable_dimms;
module_param(force_enable_dimms, bool, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(force_enable_dimms, "Ignore _STA (ACPI DIMM device) status");
-static unsigned int scrub_timeout = NFIT_ARS_TIMEOUT;
-module_param(scrub_timeout, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(scrub_timeout, "Initial scrub timeout in seconds");
-
-/* after three payloads of overflow, it's dead jim */
-static unsigned int scrub_overflow_abort = 3;
-module_param(scrub_overflow_abort, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(scrub_overflow_abort,
- "Number of times we overflow ARS results before abort");
-
static bool disable_vendor_specific;
module_param(disable_vendor_specific, bool, S_IRUGO);
MODULE_PARM_DESC(disable_vendor_specific,
@@ -60,6 +50,10 @@ module_param(default_dsm_family, int, S_IRUGO);
MODULE_PARM_DESC(default_dsm_family,
"Try this DSM type first when identifying NVDIMM family");
+static bool no_init_ars;
+module_param(no_init_ars, bool, 0644);
+MODULE_PARM_DESC(no_init_ars, "Skip ARS run at nfit init time");
+
LIST_HEAD(acpi_descs);
DEFINE_MUTEX(acpi_desc_lock);
@@ -197,7 +191,7 @@ static int xlat_nvdimm_status(struct nvdimm *nvdimm, void *buf, unsigned int cmd
* In the _LSI, _LSR, _LSW case the locked status is
* communicated via the read/write commands
*/
- if (nfit_mem->has_lsi)
+ if (nfit_mem->has_lsr)
break;
if (status >> 16 & ND_CONFIG_LOCKED)
@@ -477,14 +471,14 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
in_buf.buffer.length = call_pkg->nd_size_in;
}
- dev_dbg(dev, "%s:%s cmd: %d: func: %d input length: %d\n",
- __func__, dimm_name, cmd, func, in_buf.buffer.length);
+ dev_dbg(dev, "%s cmd: %d: func: %d input length: %d\n",
+ dimm_name, cmd, func, in_buf.buffer.length);
print_hex_dump_debug("nvdimm in ", DUMP_PREFIX_OFFSET, 4, 4,
in_buf.buffer.pointer,
min_t(u32, 256, in_buf.buffer.length), true);
/* call the BIOS, prefer the named methods over _DSM if available */
- if (nvdimm && cmd == ND_CMD_GET_CONFIG_SIZE && nfit_mem->has_lsi)
+ if (nvdimm && cmd == ND_CMD_GET_CONFIG_SIZE && nfit_mem->has_lsr)
out_obj = acpi_label_info(handle);
else if (nvdimm && cmd == ND_CMD_GET_CONFIG_DATA && nfit_mem->has_lsr) {
struct nd_cmd_get_config_data_hdr *p = buf;
@@ -507,8 +501,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
}
if (!out_obj) {
- dev_dbg(dev, "%s:%s _DSM failed cmd: %s\n", __func__, dimm_name,
- cmd_name);
+ dev_dbg(dev, "%s _DSM failed cmd: %s\n", dimm_name, cmd_name);
return -EINVAL;
}
@@ -529,13 +522,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
}
if (out_obj->package.type != ACPI_TYPE_BUFFER) {
- dev_dbg(dev, "%s:%s unexpected output object type cmd: %s type: %d\n",
- __func__, dimm_name, cmd_name, out_obj->type);
+ dev_dbg(dev, "%s unexpected output object type cmd: %s type: %d\n",
+ dimm_name, cmd_name, out_obj->type);
rc = -EINVAL;
goto out;
}
- dev_dbg(dev, "%s:%s cmd: %s output length: %d\n", __func__, dimm_name,
+ dev_dbg(dev, "%s cmd: %s output length: %d\n", dimm_name,
cmd_name, out_obj->buffer.length);
print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4, 4,
out_obj->buffer.pointer,
@@ -547,14 +540,14 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
out_obj->buffer.length - offset);
if (offset + out_size > out_obj->buffer.length) {
- dev_dbg(dev, "%s:%s output object underflow cmd: %s field: %d\n",
- __func__, dimm_name, cmd_name, i);
+ dev_dbg(dev, "%s output object underflow cmd: %s field: %d\n",
+ dimm_name, cmd_name, i);
break;
}
if (in_buf.buffer.length + offset + out_size > buf_len) {
- dev_dbg(dev, "%s:%s output overrun cmd: %s field: %d\n",
- __func__, dimm_name, cmd_name, i);
+ dev_dbg(dev, "%s output overrun cmd: %s field: %d\n",
+ dimm_name, cmd_name, i);
rc = -ENXIO;
goto out;
}
@@ -656,7 +649,7 @@ static bool add_spa(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_spa->list);
memcpy(nfit_spa->spa, spa, sizeof(*spa));
list_add_tail(&nfit_spa->list, &acpi_desc->spas);
- dev_dbg(dev, "%s: spa index: %d type: %s\n", __func__,
+ dev_dbg(dev, "spa index: %d type: %s\n",
spa->range_index,
spa_type_name(nfit_spa_type(spa)));
return true;
@@ -685,8 +678,8 @@ static bool add_memdev(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_memdev->list);
memcpy(nfit_memdev->memdev, memdev, sizeof(*memdev));
list_add_tail(&nfit_memdev->list, &acpi_desc->memdevs);
- dev_dbg(dev, "%s: memdev handle: %#x spa: %d dcr: %d flags: %#x\n",
- __func__, memdev->device_handle, memdev->range_index,
+ dev_dbg(dev, "memdev handle: %#x spa: %d dcr: %d flags: %#x\n",
+ memdev->device_handle, memdev->range_index,
memdev->region_index, memdev->flags);
return true;
}
@@ -754,7 +747,7 @@ static bool add_dcr(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_dcr->list);
memcpy(nfit_dcr->dcr, dcr, sizeof_dcr(dcr));
list_add_tail(&nfit_dcr->list, &acpi_desc->dcrs);
- dev_dbg(dev, "%s: dcr index: %d windows: %d\n", __func__,
+ dev_dbg(dev, "dcr index: %d windows: %d\n",
dcr->region_index, dcr->windows);
return true;
}
@@ -781,7 +774,7 @@ static bool add_bdw(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_bdw->list);
memcpy(nfit_bdw->bdw, bdw, sizeof(*bdw));
list_add_tail(&nfit_bdw->list, &acpi_desc->bdws);
- dev_dbg(dev, "%s: bdw dcr: %d windows: %d\n", __func__,
+ dev_dbg(dev, "bdw dcr: %d windows: %d\n",
bdw->region_index, bdw->windows);
return true;
}
@@ -820,7 +813,7 @@ static bool add_idt(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_idt->list);
memcpy(nfit_idt->idt, idt, sizeof_idt(idt));
list_add_tail(&nfit_idt->list, &acpi_desc->idts);
- dev_dbg(dev, "%s: idt index: %d num_lines: %d\n", __func__,
+ dev_dbg(dev, "idt index: %d num_lines: %d\n",
idt->interleave_index, idt->line_count);
return true;
}
@@ -860,7 +853,7 @@ static bool add_flush(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_flush->list);
memcpy(nfit_flush->flush, flush, sizeof_flush(flush));
list_add_tail(&nfit_flush->list, &acpi_desc->flushes);
- dev_dbg(dev, "%s: nfit_flush handle: %d hint_count: %d\n", __func__,
+ dev_dbg(dev, "nfit_flush handle: %d hint_count: %d\n",
flush->device_handle, flush->hint_count);
return true;
}
@@ -873,7 +866,7 @@ static bool add_platform_cap(struct acpi_nfit_desc *acpi_desc,
mask = (1 << (pcap->highest_capability + 1)) - 1;
acpi_desc->platform_cap = pcap->capabilities & mask;
- dev_dbg(dev, "%s: cap: %#x\n", __func__, acpi_desc->platform_cap);
+ dev_dbg(dev, "cap: %#x\n", acpi_desc->platform_cap);
return true;
}
@@ -920,7 +913,7 @@ static void *add_table(struct acpi_nfit_desc *acpi_desc,
return err;
break;
case ACPI_NFIT_TYPE_SMBIOS:
- dev_dbg(dev, "%s: smbios\n", __func__);
+ dev_dbg(dev, "smbios\n");
break;
case ACPI_NFIT_TYPE_CAPABILITIES:
if (!add_platform_cap(acpi_desc, table))
@@ -1277,8 +1270,11 @@ static ssize_t scrub_show(struct device *dev,
if (nd_desc) {
struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
+ mutex_lock(&acpi_desc->init_mutex);
rc = sprintf(buf, "%d%s", acpi_desc->scrub_count,
- (work_busy(&acpi_desc->work)) ? "+\n" : "\n");
+ work_busy(&acpi_desc->dwork.work)
+ && !acpi_desc->cancel ? "+\n" : "\n");
+ mutex_unlock(&acpi_desc->init_mutex);
}
device_unlock(dev);
return rc;
@@ -1648,7 +1644,7 @@ void __acpi_nvdimm_notify(struct device *dev, u32 event)
struct nfit_mem *nfit_mem;
struct acpi_nfit_desc *acpi_desc;
- dev_dbg(dev->parent, "%s: %s: event: %d\n", dev_name(dev), __func__,
+ dev_dbg(dev->parent, "%s: event: %d\n", dev_name(dev),
event);
if (event != NFIT_NOTIFY_DIMM_HEALTH) {
@@ -1681,12 +1677,23 @@ static void acpi_nvdimm_notify(acpi_handle handle, u32 event, void *data)
device_unlock(dev->parent);
}
+static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
+{
+ acpi_handle handle;
+ acpi_status status;
+
+ status = acpi_get_handle(adev->handle, method, &handle);
+
+ if (ACPI_SUCCESS(status))
+ return true;
+ return false;
+}
+
static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
struct nfit_mem *nfit_mem, u32 device_handle)
{
struct acpi_device *adev, *adev_dimm;
struct device *dev = acpi_desc->dev;
- union acpi_object *obj;
unsigned long dsm_mask;
const guid_t *guid;
int i;
@@ -1759,25 +1766,15 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
1ULL << i))
set_bit(i, &nfit_mem->dsm_mask);
- obj = acpi_label_info(adev_dimm->handle);
- if (obj) {
- ACPI_FREE(obj);
- nfit_mem->has_lsi = 1;
- dev_dbg(dev, "%s: has _LSI\n", dev_name(&adev_dimm->dev));
- }
-
- obj = acpi_label_read(adev_dimm->handle, 0, 0);
- if (obj) {
- ACPI_FREE(obj);
- nfit_mem->has_lsr = 1;
+ if (acpi_nvdimm_has_method(adev_dimm, "_LSI")
+ && acpi_nvdimm_has_method(adev_dimm, "_LSR")) {
dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev));
+ nfit_mem->has_lsr = true;
}
- obj = acpi_label_write(adev_dimm->handle, 0, 0, NULL);
- if (obj) {
- ACPI_FREE(obj);
- nfit_mem->has_lsw = 1;
+ if (nfit_mem->has_lsr && acpi_nvdimm_has_method(adev_dimm, "_LSW")) {
dev_dbg(dev, "%s: has _LSW\n", dev_name(&adev_dimm->dev));
+ nfit_mem->has_lsw = true;
}
return 0;
@@ -1866,10 +1863,10 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
cmd_mask |= nfit_mem->dsm_mask & NVDIMM_STANDARD_CMDMASK;
}
- if (nfit_mem->has_lsi)
+ if (nfit_mem->has_lsr) {
set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask);
- if (nfit_mem->has_lsr)
set_bit(ND_CMD_GET_CONFIG_DATA, &cmd_mask);
+ }
if (nfit_mem->has_lsw)
set_bit(ND_CMD_SET_CONFIG_DATA, &cmd_mask);
@@ -2365,7 +2362,7 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
nvdimm = nd_blk_region_to_dimm(ndbr);
nfit_mem = nvdimm_provider_data(nvdimm);
if (!nfit_mem || !nfit_mem->dcr || !nfit_mem->bdw) {
- dev_dbg(dev, "%s: missing%s%s%s\n", __func__,
+ dev_dbg(dev, "missing%s%s%s\n",
nfit_mem ? "" : " nfit_mem",
(nfit_mem && nfit_mem->dcr) ? "" : " dcr",
(nfit_mem && nfit_mem->bdw) ? "" : " bdw");
@@ -2384,7 +2381,7 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
mmio->addr.base = devm_nvdimm_memremap(dev, nfit_mem->spa_bdw->address,
nfit_mem->spa_bdw->length, nd_blk_memremap_flags(ndbr));
if (!mmio->addr.base) {
- dev_dbg(dev, "%s: %s failed to map bdw\n", __func__,
+ dev_dbg(dev, "%s failed to map bdw\n",
nvdimm_name(nvdimm));
return -ENOMEM;
}
@@ -2395,8 +2392,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
rc = nfit_blk_init_interleave(mmio, nfit_mem->idt_bdw,
nfit_mem->memdev_bdw->interleave_ways);
if (rc) {
- dev_dbg(dev, "%s: %s failed to init bdw interleave\n",
- __func__, nvdimm_name(nvdimm));
+ dev_dbg(dev, "%s failed to init bdw interleave\n",
+ nvdimm_name(nvdimm));
return rc;
}
@@ -2407,7 +2404,7 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
mmio->addr.base = devm_nvdimm_ioremap(dev, nfit_mem->spa_dcr->address,
nfit_mem->spa_dcr->length);
if (!mmio->addr.base) {
- dev_dbg(dev, "%s: %s failed to map dcr\n", __func__,
+ dev_dbg(dev, "%s failed to map dcr\n",
nvdimm_name(nvdimm));
return -ENOMEM;
}
@@ -2418,15 +2415,15 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
rc = nfit_blk_init_interleave(mmio, nfit_mem->idt_dcr,
nfit_mem->memdev_dcr->interleave_ways);
if (rc) {
- dev_dbg(dev, "%s: %s failed to init dcr interleave\n",
- __func__, nvdimm_name(nvdimm));
+ dev_dbg(dev, "%s failed to init dcr interleave\n",
+ nvdimm_name(nvdimm));
return rc;
}
rc = acpi_nfit_blk_get_flags(nd_desc, nvdimm, nfit_blk);
if (rc < 0) {
- dev_dbg(dev, "%s: %s failed get DIMM flags\n",
- __func__, nvdimm_name(nvdimm));
+ dev_dbg(dev, "%s failed get DIMM flags\n",
+ nvdimm_name(nvdimm));
return rc;
}
@@ -2476,7 +2473,8 @@ static int ars_start(struct acpi_nfit_desc *acpi_desc, struct nfit_spa *nfit_spa
memset(&ars_start, 0, sizeof(ars_start));
ars_start.address = spa->address;
ars_start.length = spa->length;
- ars_start.flags = acpi_desc->ars_start_flags;
+ if (test_bit(ARS_SHORT, &nfit_spa->ars_state))
+ ars_start.flags = ND_ARS_RETURN_PREV_DATA;
if (nfit_spa_type(spa) == NFIT_SPA_PM)
ars_start.type = ND_ARS_PERSISTENT;
else if (nfit_spa_type(spa) == NFIT_SPA_VOLATILE)
@@ -2518,16 +2516,62 @@ static int ars_get_status(struct acpi_nfit_desc *acpi_desc)
int rc, cmd_rc;
rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_STATUS, ars_status,
- acpi_desc->ars_status_size, &cmd_rc);
+ acpi_desc->max_ars, &cmd_rc);
if (rc < 0)
return rc;
return cmd_rc;
}
-static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc,
- struct nd_cmd_ars_status *ars_status)
+static void ars_complete(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_spa *nfit_spa)
+{
+ struct nd_cmd_ars_status *ars_status = acpi_desc->ars_status;
+ struct acpi_nfit_system_address *spa = nfit_spa->spa;
+ struct nd_region *nd_region = nfit_spa->nd_region;
+ struct device *dev;
+
+ if ((ars_status->address >= spa->address && ars_status->address
+ < spa->address + spa->length)
+ || (ars_status->address < spa->address)) {
+ /*
+ * Assume that if a scrub starts at an offset from the
+ * start of nfit_spa that we are in the continuation
+ * case.
+ *
+ * Otherwise, if the scrub covers the spa range, mark
+ * any pending request complete.
+ */
+ if (ars_status->address + ars_status->length
+ >= spa->address + spa->length)
+ /* complete */;
+ else
+ return;
+ } else
+ return;
+
+ if (test_bit(ARS_DONE, &nfit_spa->ars_state))
+ return;
+
+ if (!test_and_clear_bit(ARS_REQ, &nfit_spa->ars_state))
+ return;
+
+ if (nd_region) {
+ dev = nd_region_dev(nd_region);
+ nvdimm_region_notify(nd_region, NVDIMM_REVALIDATE_POISON);
+ } else
+ dev = acpi_desc->dev;
+
+ dev_dbg(dev, "ARS: range %d %s complete\n", spa->range_index,
+ test_bit(ARS_SHORT, &nfit_spa->ars_state)
+ ? "short" : "long");
+ clear_bit(ARS_SHORT, &nfit_spa->ars_state);
+ set_bit(ARS_DONE, &nfit_spa->ars_state);
+}
+
+static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc)
{
struct nvdimm_bus *nvdimm_bus = acpi_desc->nvdimm_bus;
+ struct nd_cmd_ars_status *ars_status = acpi_desc->ars_status;
int rc;
u32 i;
@@ -2606,7 +2650,7 @@ static int acpi_nfit_init_mapping(struct acpi_nfit_desc *acpi_desc,
struct acpi_nfit_system_address *spa = nfit_spa->spa;
struct nd_blk_region_desc *ndbr_desc;
struct nfit_mem *nfit_mem;
- int blk_valid = 0, rc;
+ int rc;
if (!nvdimm) {
dev_err(acpi_desc->dev, "spa%d dimm: %#x not found\n",
@@ -2626,15 +2670,14 @@ static int acpi_nfit_init_mapping(struct acpi_nfit_desc *acpi_desc,
if (!nfit_mem || !nfit_mem->bdw) {
dev_dbg(acpi_desc->dev, "spa%d %s missing bdw\n",
spa->range_index, nvdimm_name(nvdimm));
- } else {
- mapping->size = nfit_mem->bdw->capacity;
- mapping->start = nfit_mem->bdw->start_address;
- ndr_desc->num_lanes = nfit_mem->bdw->windows;
- blk_valid = 1;
+ break;
}
+ mapping->size = nfit_mem->bdw->capacity;
+ mapping->start = nfit_mem->bdw->start_address;
+ ndr_desc->num_lanes = nfit_mem->bdw->windows;
ndr_desc->mapping = mapping;
- ndr_desc->num_mappings = blk_valid;
+ ndr_desc->num_mappings = 1;
ndbr_desc = to_blk_region_desc(ndr_desc);
ndbr_desc->enable = acpi_nfit_blk_region_enable;
ndbr_desc->do_io = acpi_desc->blk_do_io;
@@ -2682,8 +2725,7 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
return 0;
if (spa->range_index == 0 && !nfit_spa_is_virtual(spa)) {
- dev_dbg(acpi_desc->dev, "%s: detected invalid spa index\n",
- __func__);
+ dev_dbg(acpi_desc->dev, "detected invalid spa index\n");
return 0;
}
@@ -2769,301 +2811,243 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
return rc;
}
-static int ars_status_alloc(struct acpi_nfit_desc *acpi_desc,
- u32 max_ars)
+static int ars_status_alloc(struct acpi_nfit_desc *acpi_desc)
{
struct device *dev = acpi_desc->dev;
struct nd_cmd_ars_status *ars_status;
- if (acpi_desc->ars_status && acpi_desc->ars_status_size >= max_ars) {
- memset(acpi_desc->ars_status, 0, acpi_desc->ars_status_size);
+ if (acpi_desc->ars_status) {
+ memset(acpi_desc->ars_status, 0, acpi_desc->max_ars);
return 0;
}
- if (acpi_desc->ars_status)
- devm_kfree(dev, acpi_desc->ars_status);
- acpi_desc->ars_status = NULL;
- ars_status = devm_kzalloc(dev, max_ars, GFP_KERNEL);
+ ars_status = devm_kzalloc(dev, acpi_desc->max_ars, GFP_KERNEL);
if (!ars_status)
return -ENOMEM;
acpi_desc->ars_status = ars_status;
- acpi_desc->ars_status_size = max_ars;
return 0;
}
-static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc,
- struct nfit_spa *nfit_spa)
+static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc)
{
- struct acpi_nfit_system_address *spa = nfit_spa->spa;
int rc;
- if (!nfit_spa->max_ars) {
- struct nd_cmd_ars_cap ars_cap;
-
- memset(&ars_cap, 0, sizeof(ars_cap));
- rc = ars_get_cap(acpi_desc, &ars_cap, nfit_spa);
- if (rc < 0)
- return rc;
- nfit_spa->max_ars = ars_cap.max_ars_out;
- nfit_spa->clear_err_unit = ars_cap.clear_err_unit;
- /* check that the supported scrub types match the spa type */
- if (nfit_spa_type(spa) == NFIT_SPA_VOLATILE &&
- ((ars_cap.status >> 16) & ND_ARS_VOLATILE) == 0)
- return -ENOTTY;
- else if (nfit_spa_type(spa) == NFIT_SPA_PM &&
- ((ars_cap.status >> 16) & ND_ARS_PERSISTENT) == 0)
- return -ENOTTY;
- }
-
- if (ars_status_alloc(acpi_desc, nfit_spa->max_ars))
+ if (ars_status_alloc(acpi_desc))
return -ENOMEM;
rc = ars_get_status(acpi_desc);
+
if (rc < 0 && rc != -ENOSPC)
return rc;
- if (ars_status_process_records(acpi_desc, acpi_desc->ars_status))
+ if (ars_status_process_records(acpi_desc))
return -ENOMEM;
return 0;
}
-static void acpi_nfit_async_scrub(struct acpi_nfit_desc *acpi_desc,
- struct nfit_spa *nfit_spa)
+static int ars_register(struct acpi_nfit_desc *acpi_desc, struct nfit_spa *nfit_spa,
+ int *query_rc)
{
- struct acpi_nfit_system_address *spa = nfit_spa->spa;
- unsigned int overflow_retry = scrub_overflow_abort;
- u64 init_ars_start = 0, init_ars_len = 0;
- struct device *dev = acpi_desc->dev;
- unsigned int tmo = scrub_timeout;
- int rc;
+ int rc = *query_rc;
- if (!nfit_spa->ars_required || !nfit_spa->nd_region)
- return;
+ if (no_init_ars)
+ return acpi_nfit_register_region(acpi_desc, nfit_spa);
- rc = ars_start(acpi_desc, nfit_spa);
- /*
- * If we timed out the initial scan we'll still be busy here,
- * and will wait another timeout before giving up permanently.
- */
- if (rc < 0 && rc != -EBUSY)
- return;
-
- do {
- u64 ars_start, ars_len;
-
- if (acpi_desc->cancel)
- break;
- rc = acpi_nfit_query_poison(acpi_desc, nfit_spa);
- if (rc == -ENOTTY)
- break;
- if (rc == -EBUSY && !tmo) {
- dev_warn(dev, "range %d ars timeout, aborting\n",
- spa->range_index);
- break;
- }
+ set_bit(ARS_REQ, &nfit_spa->ars_state);
+ set_bit(ARS_SHORT, &nfit_spa->ars_state);
+ switch (rc) {
+ case 0:
+ case -EAGAIN:
+ rc = ars_start(acpi_desc, nfit_spa);
if (rc == -EBUSY) {
- /*
- * Note, entries may be appended to the list
- * while the lock is dropped, but the workqueue
- * being active prevents entries being deleted /
- * freed.
- */
- mutex_unlock(&acpi_desc->init_mutex);
- ssleep(1);
- tmo--;
- mutex_lock(&acpi_desc->init_mutex);
- continue;
- }
-
- /* we got some results, but there are more pending... */
- if (rc == -ENOSPC && overflow_retry--) {
- if (!init_ars_len) {
- init_ars_len = acpi_desc->ars_status->length;
- init_ars_start = acpi_desc->ars_status->address;
- }
- rc = ars_continue(acpi_desc);
- }
-
- if (rc < 0) {
- dev_warn(dev, "range %d ars continuation failed\n",
- spa->range_index);
+ *query_rc = rc;
break;
- }
-
- if (init_ars_len) {
- ars_start = init_ars_start;
- ars_len = init_ars_len;
+ } else if (rc == 0) {
+ rc = acpi_nfit_query_poison(acpi_desc);
} else {
- ars_start = acpi_desc->ars_status->address;
- ars_len = acpi_desc->ars_status->length;
+ set_bit(ARS_FAILED, &nfit_spa->ars_state);
+ break;
}
- dev_dbg(dev, "spa range: %d ars from %#llx + %#llx complete\n",
- spa->range_index, ars_start, ars_len);
- /* notify the region about new poison entries */
- nvdimm_region_notify(nfit_spa->nd_region,
- NVDIMM_REVALIDATE_POISON);
+ if (rc == -EAGAIN)
+ clear_bit(ARS_SHORT, &nfit_spa->ars_state);
+ else if (rc == 0)
+ ars_complete(acpi_desc, nfit_spa);
break;
- } while (1);
+ case -EBUSY:
+ case -ENOSPC:
+ break;
+ default:
+ set_bit(ARS_FAILED, &nfit_spa->ars_state);
+ break;
+ }
+
+ if (test_and_clear_bit(ARS_DONE, &nfit_spa->ars_state))
+ set_bit(ARS_REQ, &nfit_spa->ars_state);
+
+ return acpi_nfit_register_region(acpi_desc, nfit_spa);
}
-static void acpi_nfit_scrub(struct work_struct *work)
+static void ars_complete_all(struct acpi_nfit_desc *acpi_desc)
{
- struct device *dev;
- u64 init_scrub_length = 0;
struct nfit_spa *nfit_spa;
- u64 init_scrub_address = 0;
- bool init_ars_done = false;
- struct acpi_nfit_desc *acpi_desc;
- unsigned int tmo = scrub_timeout;
- unsigned int overflow_retry = scrub_overflow_abort;
-
- acpi_desc = container_of(work, typeof(*acpi_desc), work);
- dev = acpi_desc->dev;
-
- /*
- * We scrub in 2 phases. The first phase waits for any platform
- * firmware initiated scrubs to complete and then we go search for the
- * affected spa regions to mark them scanned. In the second phase we
- * initiate a directed scrub for every range that was not scrubbed in
- * phase 1. If we're called for a 'rescan', we harmlessly pass through
- * the first phase, but really only care about running phase 2, where
- * regions can be notified of new poison.
- */
- /* process platform firmware initiated scrubs */
- retry:
- mutex_lock(&acpi_desc->init_mutex);
list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
- struct nd_cmd_ars_status *ars_status;
- struct acpi_nfit_system_address *spa;
- u64 ars_start, ars_len;
- int rc;
-
- if (acpi_desc->cancel)
- break;
-
- if (nfit_spa->nd_region)
+ if (test_bit(ARS_FAILED, &nfit_spa->ars_state))
continue;
+ ars_complete(acpi_desc, nfit_spa);
+ }
+}
- if (init_ars_done) {
- /*
- * No need to re-query, we're now just
- * reconciling all the ranges covered by the
- * initial scrub
- */
- rc = 0;
- } else
- rc = acpi_nfit_query_poison(acpi_desc, nfit_spa);
-
- if (rc == -ENOTTY) {
- /* no ars capability, just register spa and move on */
- acpi_nfit_register_region(acpi_desc, nfit_spa);
- continue;
- }
-
- if (rc == -EBUSY && !tmo) {
- /* fallthrough to directed scrub in phase 2 */
- dev_warn(dev, "timeout awaiting ars results, continuing...\n");
- break;
- } else if (rc == -EBUSY) {
- mutex_unlock(&acpi_desc->init_mutex);
- ssleep(1);
- tmo--;
- goto retry;
- }
-
- /* we got some results, but there are more pending... */
- if (rc == -ENOSPC && overflow_retry--) {
- ars_status = acpi_desc->ars_status;
- /*
- * Record the original scrub range, so that we
- * can recall all the ranges impacted by the
- * initial scrub.
- */
- if (!init_scrub_length) {
- init_scrub_length = ars_status->length;
- init_scrub_address = ars_status->address;
- }
- rc = ars_continue(acpi_desc);
- if (rc == 0) {
- mutex_unlock(&acpi_desc->init_mutex);
- goto retry;
- }
- }
+static unsigned int __acpi_nfit_scrub(struct acpi_nfit_desc *acpi_desc,
+ int query_rc)
+{
+ unsigned int tmo = acpi_desc->scrub_tmo;
+ struct device *dev = acpi_desc->dev;
+ struct nfit_spa *nfit_spa;
- if (rc < 0) {
- /*
- * Initial scrub failed, we'll give it one more
- * try below...
- */
- break;
- }
+ if (acpi_desc->cancel)
+ return 0;
- /* We got some final results, record completed ranges */
- ars_status = acpi_desc->ars_status;
- if (init_scrub_length) {
- ars_start = init_scrub_address;
- ars_len = ars_start + init_scrub_length;
- } else {
- ars_start = ars_status->address;
- ars_len = ars_status->length;
- }
- spa = nfit_spa->spa;
+ if (query_rc == -EBUSY) {
+ dev_dbg(dev, "ARS: ARS busy\n");
+ return min(30U * 60U, tmo * 2);
+ }
+ if (query_rc == -ENOSPC) {
+ dev_dbg(dev, "ARS: ARS continue\n");
+ ars_continue(acpi_desc);
+ return 1;
+ }
+ if (query_rc && query_rc != -EAGAIN) {
+ unsigned long long addr, end;
- if (!init_ars_done) {
- init_ars_done = true;
- dev_dbg(dev, "init scrub %#llx + %#llx complete\n",
- ars_start, ars_len);
- }
- if (ars_start <= spa->address && ars_start + ars_len
- >= spa->address + spa->length)
- acpi_nfit_register_region(acpi_desc, nfit_spa);
+ addr = acpi_desc->ars_status->address;
+ end = addr + acpi_desc->ars_status->length;
+ dev_dbg(dev, "ARS: %llx-%llx failed (%d)\n", addr, end,
+ query_rc);
}
- /*
- * For all the ranges not covered by an initial scrub we still
- * want to see if there are errors, but it's ok to discover them
- * asynchronously.
- */
+ ars_complete_all(acpi_desc);
list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
- /*
- * Flag all the ranges that still need scrubbing, but
- * register them now to make data available.
- */
- if (!nfit_spa->nd_region) {
- nfit_spa->ars_required = 1;
- acpi_nfit_register_region(acpi_desc, nfit_spa);
+ if (test_bit(ARS_FAILED, &nfit_spa->ars_state))
+ continue;
+ if (test_bit(ARS_REQ, &nfit_spa->ars_state)) {
+ int rc = ars_start(acpi_desc, nfit_spa);
+
+ clear_bit(ARS_DONE, &nfit_spa->ars_state);
+ dev = nd_region_dev(nfit_spa->nd_region);
+ dev_dbg(dev, "ARS: range %d ARS start (%d)\n",
+ nfit_spa->spa->range_index, rc);
+ if (rc == 0 || rc == -EBUSY)
+ return 1;
+ dev_err(dev, "ARS: range %d ARS failed (%d)\n",
+ nfit_spa->spa->range_index, rc);
+ set_bit(ARS_FAILED, &nfit_spa->ars_state);
}
}
- acpi_desc->init_complete = 1;
+ return 0;
+}
- list_for_each_entry(nfit_spa, &acpi_desc->spas, list)
- acpi_nfit_async_scrub(acpi_desc, nfit_spa);
- acpi_desc->scrub_count++;
- acpi_desc->ars_start_flags = 0;
- if (acpi_desc->scrub_count_state)
- sysfs_notify_dirent(acpi_desc->scrub_count_state);
+static void acpi_nfit_scrub(struct work_struct *work)
+{
+ struct acpi_nfit_desc *acpi_desc;
+ unsigned int tmo;
+ int query_rc;
+
+ acpi_desc = container_of(work, typeof(*acpi_desc), dwork.work);
+ mutex_lock(&acpi_desc->init_mutex);
+ query_rc = acpi_nfit_query_poison(acpi_desc);
+ tmo = __acpi_nfit_scrub(acpi_desc, query_rc);
+ if (tmo) {
+ queue_delayed_work(nfit_wq, &acpi_desc->dwork, tmo * HZ);
+ acpi_desc->scrub_tmo = tmo;
+ } else {
+ acpi_desc->scrub_count++;
+ if (acpi_desc->scrub_count_state)
+ sysfs_notify_dirent(acpi_desc->scrub_count_state);
+ }
+ memset(acpi_desc->ars_status, 0, acpi_desc->max_ars);
mutex_unlock(&acpi_desc->init_mutex);
}
+static void acpi_nfit_init_ars(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_spa *nfit_spa)
+{
+ int type = nfit_spa_type(nfit_spa->spa);
+ struct nd_cmd_ars_cap ars_cap;
+ int rc;
+
+ memset(&ars_cap, 0, sizeof(ars_cap));
+ rc = ars_get_cap(acpi_desc, &ars_cap, nfit_spa);
+ if (rc < 0)
+ return;
+ /* check that the supported scrub types match the spa type */
+ if (type == NFIT_SPA_VOLATILE && ((ars_cap.status >> 16)
+ & ND_ARS_VOLATILE) == 0)
+ return;
+ if (type == NFIT_SPA_PM && ((ars_cap.status >> 16)
+ & ND_ARS_PERSISTENT) == 0)
+ return;
+
+ nfit_spa->max_ars = ars_cap.max_ars_out;
+ nfit_spa->clear_err_unit = ars_cap.clear_err_unit;
+ acpi_desc->max_ars = max(nfit_spa->max_ars, acpi_desc->max_ars);
+ clear_bit(ARS_FAILED, &nfit_spa->ars_state);
+ set_bit(ARS_REQ, &nfit_spa->ars_state);
+}
+
static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc)
{
struct nfit_spa *nfit_spa;
- int rc;
+ int rc, query_rc;
+
+ list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
+ set_bit(ARS_FAILED, &nfit_spa->ars_state);
+ switch (nfit_spa_type(nfit_spa->spa)) {
+ case NFIT_SPA_VOLATILE:
+ case NFIT_SPA_PM:
+ acpi_nfit_init_ars(acpi_desc, nfit_spa);
+ break;
+ }
+ }
+
+ /*
+ * Reap any results that might be pending before starting new
+ * short requests.
+ */
+ query_rc = acpi_nfit_query_poison(acpi_desc);
+ if (query_rc == 0)
+ ars_complete_all(acpi_desc);
list_for_each_entry(nfit_spa, &acpi_desc->spas, list)
- if (nfit_spa_type(nfit_spa->spa) == NFIT_SPA_DCR) {
- /* BLK regions don't need to wait for ars results */
+ switch (nfit_spa_type(nfit_spa->spa)) {
+ case NFIT_SPA_VOLATILE:
+ case NFIT_SPA_PM:
+ /* register regions and kick off initial ARS run */
+ rc = ars_register(acpi_desc, nfit_spa, &query_rc);
+ if (rc)
+ return rc;
+ break;
+ case NFIT_SPA_BDW:
+ /* nothing to register */
+ break;
+ case NFIT_SPA_DCR:
+ case NFIT_SPA_VDISK:
+ case NFIT_SPA_VCD:
+ case NFIT_SPA_PDISK:
+ case NFIT_SPA_PCD:
+ /* register known regions that don't support ARS */
rc = acpi_nfit_register_region(acpi_desc, nfit_spa);
if (rc)
return rc;
+ break;
+ default:
+ /* don't register unknown regions */
+ break;
}
- acpi_desc->ars_start_flags = 0;
- if (!acpi_desc->cancel)
- queue_work(nfit_wq, &acpi_desc->work);
+ queue_delayed_work(nfit_wq, &acpi_desc->dwork, 0);
return 0;
}
@@ -3173,8 +3157,7 @@ int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *data, acpi_size sz)
data = add_table(acpi_desc, &prev, data, end);
if (IS_ERR(data)) {
- dev_dbg(dev, "%s: nfit table parsing error: %ld\n", __func__,
- PTR_ERR(data));
+ dev_dbg(dev, "nfit table parsing error: %ld\n", PTR_ERR(data));
rc = PTR_ERR(data);
goto out_unlock;
}
@@ -3199,49 +3182,20 @@ int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *data, acpi_size sz)
}
EXPORT_SYMBOL_GPL(acpi_nfit_init);
-struct acpi_nfit_flush_work {
- struct work_struct work;
- struct completion cmp;
-};
-
-static void flush_probe(struct work_struct *work)
-{
- struct acpi_nfit_flush_work *flush;
-
- flush = container_of(work, typeof(*flush), work);
- complete(&flush->cmp);
-}
-
static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
{
struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
struct device *dev = acpi_desc->dev;
- struct acpi_nfit_flush_work flush;
- int rc;
- /* bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
+ /* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
device_lock(dev);
device_unlock(dev);
- /* bounce the init_mutex to make init_complete valid */
+ /* Bounce the init_mutex to complete initial registration */
mutex_lock(&acpi_desc->init_mutex);
- if (acpi_desc->cancel || acpi_desc->init_complete) {
- mutex_unlock(&acpi_desc->init_mutex);
- return 0;
- }
-
- /*
- * Scrub work could take 10s of seconds, userspace may give up so we
- * need to be interruptible while waiting.
- */
- INIT_WORK_ONSTACK(&flush.work, flush_probe);
- init_completion(&flush.cmp);
- queue_work(nfit_wq, &flush.work);
mutex_unlock(&acpi_desc->init_mutex);
- rc = wait_for_completion_interruptible(&flush.cmp);
- cancel_work_sync(&flush.work);
- return rc;
+ return 0;
}
static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
@@ -3260,20 +3214,18 @@ static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
* just needs guarantees that any ars it initiates are not
* interrupted by any intervening start reqeusts from userspace.
*/
- if (work_busy(&acpi_desc->work))
+ if (work_busy(&acpi_desc->dwork.work))
return -EBUSY;
return 0;
}
-int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, u8 flags)
+int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, unsigned long flags)
{
struct device *dev = acpi_desc->dev;
+ int scheduled = 0, busy = 0;
struct nfit_spa *nfit_spa;
- if (work_busy(&acpi_desc->work))
- return -EBUSY;
-
mutex_lock(&acpi_desc->init_mutex);
if (acpi_desc->cancel) {
mutex_unlock(&acpi_desc->init_mutex);
@@ -3281,19 +3233,32 @@ int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, u8 flags)
}
list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
- struct acpi_nfit_system_address *spa = nfit_spa->spa;
+ int type = nfit_spa_type(nfit_spa->spa);
- if (nfit_spa_type(spa) != NFIT_SPA_PM)
+ if (type != NFIT_SPA_PM && type != NFIT_SPA_VOLATILE)
+ continue;
+ if (test_bit(ARS_FAILED, &nfit_spa->ars_state))
continue;
- nfit_spa->ars_required = 1;
+ if (test_and_set_bit(ARS_REQ, &nfit_spa->ars_state))
+ busy++;
+ else {
+ if (test_bit(ARS_SHORT, &flags))
+ set_bit(ARS_SHORT, &nfit_spa->ars_state);
+ scheduled++;
+ }
+ }
+ if (scheduled) {
+ queue_delayed_work(nfit_wq, &acpi_desc->dwork, 0);
+ dev_dbg(dev, "ars_scan triggered\n");
}
- acpi_desc->ars_start_flags = flags;
- queue_work(nfit_wq, &acpi_desc->work);
- dev_dbg(dev, "%s: ars_scan triggered\n", __func__);
mutex_unlock(&acpi_desc->init_mutex);
- return 0;
+ if (scheduled)
+ return 0;
+ if (busy)
+ return -EBUSY;
+ return -ENOTTY;
}
void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev)
@@ -3320,7 +3285,8 @@ void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev)
INIT_LIST_HEAD(&acpi_desc->dimms);
INIT_LIST_HEAD(&acpi_desc->list);
mutex_init(&acpi_desc->init_mutex);
- INIT_WORK(&acpi_desc->work, acpi_nfit_scrub);
+ acpi_desc->scrub_tmo = 1;
+ INIT_DELAYED_WORK(&acpi_desc->dwork, acpi_nfit_scrub);
}
EXPORT_SYMBOL_GPL(acpi_nfit_desc_init);
@@ -3344,6 +3310,7 @@ void acpi_nfit_shutdown(void *data)
mutex_lock(&acpi_desc->init_mutex);
acpi_desc->cancel = 1;
+ cancel_delayed_work_sync(&acpi_desc->dwork);
mutex_unlock(&acpi_desc->init_mutex);
/*
@@ -3397,8 +3364,8 @@ static int acpi_nfit_add(struct acpi_device *adev)
rc = acpi_nfit_init(acpi_desc, obj->buffer.pointer,
obj->buffer.length);
else
- dev_dbg(dev, "%s invalid type %d, ignoring _FIT\n",
- __func__, (int) obj->type);
+ dev_dbg(dev, "invalid type %d, ignoring _FIT\n",
+ (int) obj->type);
kfree(buf.pointer);
} else
/* skip over the lead-in header table */
@@ -3427,7 +3394,7 @@ static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle)
if (!dev->driver) {
/* dev->driver may be null if we're being removed */
- dev_dbg(dev, "%s: no driver found for dev\n", __func__);
+ dev_dbg(dev, "no driver found for dev\n");
return;
}
@@ -3465,15 +3432,15 @@ static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle)
static void acpi_nfit_uc_error_notify(struct device *dev, acpi_handle handle)
{
struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(dev);
- u8 flags = (acpi_desc->scrub_mode == HW_ERROR_SCRUB_ON) ?
- 0 : ND_ARS_RETURN_PREV_DATA;
+ unsigned long flags = (acpi_desc->scrub_mode == HW_ERROR_SCRUB_ON) ?
+ 0 : 1 << ARS_SHORT;
acpi_nfit_ars_rescan(acpi_desc, flags);
}
void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event)
{
- dev_dbg(dev, "%s: event: 0x%x\n", __func__, event);
+ dev_dbg(dev, "event: 0x%x\n", event);
switch (event) {
case NFIT_NOTIFY_UPDATE:
diff --git a/drivers/acpi/nfit/mce.c b/drivers/acpi/nfit/mce.c
index b92921439657..e9626bf6ca29 100644
--- a/drivers/acpi/nfit/mce.c
+++ b/drivers/acpi/nfit/mce.c
@@ -51,9 +51,8 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val,
if ((spa->address + spa->length - 1) < mce->addr)
continue;
found_match = 1;
- dev_dbg(dev, "%s: addr in SPA %d (0x%llx, 0x%llx)\n",
- __func__, spa->range_index, spa->address,
- spa->length);
+ dev_dbg(dev, "addr in SPA %d (0x%llx, 0x%llx)\n",
+ spa->range_index, spa->address, spa->length);
/*
* We can break at the first match because we're going
* to rescan all the SPA ranges. There shouldn't be any
diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h
index 50d36e166d70..7d15856a739f 100644
--- a/drivers/acpi/nfit/nfit.h
+++ b/drivers/acpi/nfit/nfit.h
@@ -117,10 +117,17 @@ enum nfit_dimm_notifiers {
NFIT_NOTIFY_DIMM_HEALTH = 0x81,
};
+enum nfit_ars_state {
+ ARS_REQ,
+ ARS_DONE,
+ ARS_SHORT,
+ ARS_FAILED,
+};
+
struct nfit_spa {
struct list_head list;
struct nd_region *nd_region;
- unsigned int ars_required:1;
+ unsigned long ars_state;
u32 clear_err_unit;
u32 max_ars;
struct acpi_nfit_system_address spa[0];
@@ -171,9 +178,8 @@ struct nfit_mem {
struct resource *flush_wpq;
unsigned long dsm_mask;
int family;
- u32 has_lsi:1;
- u32 has_lsr:1;
- u32 has_lsw:1;
+ bool has_lsr;
+ bool has_lsw;
};
struct acpi_nfit_desc {
@@ -191,18 +197,18 @@ struct acpi_nfit_desc {
struct device *dev;
u8 ars_start_flags;
struct nd_cmd_ars_status *ars_status;
- size_t ars_status_size;
- struct work_struct work;
+ struct delayed_work dwork;
struct list_head list;
struct kernfs_node *scrub_count_state;
+ unsigned int max_ars;
unsigned int scrub_count;
unsigned int scrub_mode;
unsigned int cancel:1;
- unsigned int init_complete:1;
unsigned long dimm_cmd_force_en;
unsigned long bus_cmd_force_en;
unsigned long bus_nfit_cmd_force_en;
unsigned int platform_cap;
+ unsigned int scrub_tmo;
int (*blk_do_io)(struct nd_blk_region *ndbr, resource_size_t dpa,
void *iobuf, u64 len, int rw);
};
@@ -244,7 +250,7 @@ struct nfit_blk {
extern struct list_head acpi_descs;
extern struct mutex acpi_desc_lock;
-int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, u8 flags);
+int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, unsigned long flags);
#ifdef CONFIG_X86_MCE
void nfit_mce_register(void);
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index c7cf48ad5cb9..a651ab3490d8 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -533,7 +533,7 @@ int acpi_processor_notify_smm(struct module *calling_module)
EXPORT_SYMBOL(acpi_processor_notify_smm);
-static int acpi_processor_get_psd(struct acpi_processor *pr)
+int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain)
{
int result = 0;
acpi_status status = AE_OK;
@@ -541,9 +541,8 @@ static int acpi_processor_get_psd(struct acpi_processor *pr)
struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"};
struct acpi_buffer state = {0, NULL};
union acpi_object *psd = NULL;
- struct acpi_psd_package *pdomain;
- status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer);
+ status = acpi_evaluate_object(handle, "_PSD", NULL, &buffer);
if (ACPI_FAILURE(status)) {
return -ENODEV;
}
@@ -561,8 +560,6 @@ static int acpi_processor_get_psd(struct acpi_processor *pr)
goto end;
}
- pdomain = &(pr->performance->domain_info);
-
state.length = sizeof(struct acpi_psd_package);
state.pointer = pdomain;
@@ -597,6 +594,7 @@ end:
kfree(buffer.pointer);
return result;
}
+EXPORT_SYMBOL(acpi_processor_get_psd);
int acpi_processor_preregister_performance(
struct acpi_processor_performance __percpu *performance)
@@ -645,7 +643,8 @@ int acpi_processor_preregister_performance(
pr->performance = per_cpu_ptr(performance, i);
cpumask_set_cpu(i, pr->performance->shared_cpu_map);
- if (acpi_processor_get_psd(pr)) {
+ pdomain = &(pr->performance->domain_info);
+ if (acpi_processor_get_psd(pr->handle, pdomain)) {
retval = -EINVAL;
continue;
}
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 79fcd2bae96b..bffe8616bd55 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -837,11 +837,8 @@ int __init memory_dev_init(void)
* during boot and have been initialized
*/
mutex_lock(&mem_sysfs_mutex);
- for (i = 0; i < NR_MEM_SECTIONS; i += sections_per_block) {
- /* Don't iterate over sections we know are !present: */
- if (i > __highest_present_section_nr)
- break;
-
+ for (i = 0; i <= __highest_present_section_nr;
+ i += sections_per_block) {
err = add_memory_block(i);
if (!ret)
ret = err;
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 1e03b04819c8..07dc5419bd63 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -32,6 +32,7 @@
#include <linux/ceph/osd_client.h>
#include <linux/ceph/mon_client.h>
#include <linux/ceph/cls_lock_client.h>
+#include <linux/ceph/striper.h>
#include <linux/ceph/decode.h>
#include <linux/parser.h>
#include <linux/bsearch.h>
@@ -200,95 +201,81 @@ struct rbd_client {
};
struct rbd_img_request;
-typedef void (*rbd_img_callback_t)(struct rbd_img_request *);
-
-#define BAD_WHICH U32_MAX /* Good which or bad which, which? */
-
-struct rbd_obj_request;
-typedef void (*rbd_obj_callback_t)(struct rbd_obj_request *);
enum obj_request_type {
- OBJ_REQUEST_NODATA, OBJ_REQUEST_BIO, OBJ_REQUEST_PAGES
+ OBJ_REQUEST_NODATA = 1,
+ OBJ_REQUEST_BIO, /* pointer into provided bio (list) */
+ OBJ_REQUEST_BVECS, /* pointer into provided bio_vec array */
+ OBJ_REQUEST_OWN_BVECS, /* private bio_vec array, doesn't own pages */
};
enum obj_operation_type {
+ OBJ_OP_READ = 1,
OBJ_OP_WRITE,
- OBJ_OP_READ,
OBJ_OP_DISCARD,
};
-enum obj_req_flags {
- OBJ_REQ_DONE, /* completion flag: not done = 0, done = 1 */
- OBJ_REQ_IMG_DATA, /* object usage: standalone = 0, image = 1 */
- OBJ_REQ_KNOWN, /* EXISTS flag valid: no = 0, yes = 1 */
- OBJ_REQ_EXISTS, /* target exists: no = 0, yes = 1 */
+/*
+ * Writes go through the following state machine to deal with
+ * layering:
+ *
+ * need copyup
+ * RBD_OBJ_WRITE_GUARD ---------------> RBD_OBJ_WRITE_COPYUP
+ * | ^ |
+ * v \------------------------------/
+ * done
+ * ^
+ * |
+ * RBD_OBJ_WRITE_FLAT
+ *
+ * Writes start in RBD_OBJ_WRITE_GUARD or _FLAT, depending on whether
+ * there is a parent or not.
+ */
+enum rbd_obj_write_state {
+ RBD_OBJ_WRITE_FLAT = 1,
+ RBD_OBJ_WRITE_GUARD,
+ RBD_OBJ_WRITE_COPYUP,
};
struct rbd_obj_request {
- u64 object_no;
- u64 offset; /* object start byte */
- u64 length; /* bytes from offset */
- unsigned long flags;
-
- /*
- * An object request associated with an image will have its
- * img_data flag set; a standalone object request will not.
- *
- * A standalone object request will have which == BAD_WHICH
- * and a null obj_request pointer.
- *
- * An object request initiated in support of a layered image
- * object (to check for its existence before a write) will
- * have which == BAD_WHICH and a non-null obj_request pointer.
- *
- * Finally, an object request for rbd image data will have
- * which != BAD_WHICH, and will have a non-null img_request
- * pointer. The value of which will be in the range
- * 0..(img_request->obj_request_count-1).
- */
+ struct ceph_object_extent ex;
union {
- struct rbd_obj_request *obj_request; /* STAT op */
- struct {
- struct rbd_img_request *img_request;
- u64 img_offset;
- /* links for img_request->obj_requests list */
- struct list_head links;
- };
+ bool tried_parent; /* for reads */
+ enum rbd_obj_write_state write_state; /* for writes */
};
- u32 which; /* posn image request list */
- enum obj_request_type type;
+ struct rbd_img_request *img_request;
+ struct ceph_file_extent *img_extents;
+ u32 num_img_extents;
+
union {
- struct bio *bio_list;
+ struct ceph_bio_iter bio_pos;
struct {
- struct page **pages;
- u32 page_count;
+ struct ceph_bvec_iter bvec_pos;
+ u32 bvec_count;
+ u32 bvec_idx;
};
};
- struct page **copyup_pages;
- u32 copyup_page_count;
+ struct bio_vec *copyup_bvecs;
+ u32 copyup_bvec_count;
struct ceph_osd_request *osd_req;
u64 xferred; /* bytes transferred */
int result;
- rbd_obj_callback_t callback;
-
struct kref kref;
};
enum img_req_flags {
- IMG_REQ_WRITE, /* I/O direction: read = 0, write = 1 */
IMG_REQ_CHILD, /* initiator: block = 0, child image = 1 */
IMG_REQ_LAYERED, /* ENOENT handling: normal = 0, layered = 1 */
- IMG_REQ_DISCARD, /* discard: normal = 0, discard request = 1 */
};
struct rbd_img_request {
struct rbd_device *rbd_dev;
- u64 offset; /* starting image byte offset */
- u64 length; /* byte count from offset */
+ enum obj_operation_type op_type;
+ enum obj_request_type data_type;
unsigned long flags;
union {
u64 snap_id; /* for reads */
@@ -298,26 +285,21 @@ struct rbd_img_request {
struct request *rq; /* block request */
struct rbd_obj_request *obj_request; /* obj req initiator */
};
- struct page **copyup_pages;
- u32 copyup_page_count;
- spinlock_t completion_lock;/* protects next_completion */
- u32 next_completion;
- rbd_img_callback_t callback;
+ spinlock_t completion_lock;
u64 xferred;/* aggregate bytes transferred */
int result; /* first nonzero obj_request result */
+ struct list_head object_extents; /* obj_req.ex structs */
u32 obj_request_count;
- struct list_head obj_requests; /* rbd_obj_request structs */
+ u32 pending_count;
struct kref kref;
};
#define for_each_obj_request(ireq, oreq) \
- list_for_each_entry(oreq, &(ireq)->obj_requests, links)
-#define for_each_obj_request_from(ireq, oreq) \
- list_for_each_entry_from(oreq, &(ireq)->obj_requests, links)
+ list_for_each_entry(oreq, &(ireq)->object_extents, ex.oe_item)
#define for_each_obj_request_safe(ireq, oreq, n) \
- list_for_each_entry_safe_reverse(oreq, n, &(ireq)->obj_requests, links)
+ list_for_each_entry_safe(oreq, n, &(ireq)->object_extents, ex.oe_item)
enum rbd_watch_state {
RBD_WATCH_STATE_UNREGISTERED,
@@ -433,8 +415,6 @@ static DEFINE_SPINLOCK(rbd_client_list_lock);
static struct kmem_cache *rbd_img_request_cache;
static struct kmem_cache *rbd_obj_request_cache;
-static struct bio_set *rbd_bio_clone;
-
static int rbd_major;
static DEFINE_IDA(rbd_dev_id_ida);
@@ -447,8 +427,6 @@ static bool single_major = true;
module_param(single_major, bool, S_IRUGO);
MODULE_PARM_DESC(single_major, "Use a single major number for all rbd devices (default: true)");
-static int rbd_img_request_submit(struct rbd_img_request *img_request);
-
static ssize_t rbd_add(struct bus_type *bus, const char *buf,
size_t count);
static ssize_t rbd_remove(struct bus_type *bus, const char *buf,
@@ -458,7 +436,6 @@ static ssize_t rbd_add_single_major(struct bus_type *bus, const char *buf,
static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf,
size_t count);
static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth);
-static void rbd_spec_put(struct rbd_spec *spec);
static int rbd_dev_id_to_minor(int dev_id)
{
@@ -577,9 +554,6 @@ void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...)
# define rbd_assert(expr) ((void) 0)
#endif /* !RBD_DEBUG */
-static void rbd_osd_copyup_callback(struct rbd_obj_request *obj_request);
-static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request);
-static void rbd_img_parent_read(struct rbd_obj_request *obj_request);
static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);
static int rbd_dev_refresh(struct rbd_device *rbd_dev);
@@ -857,26 +831,6 @@ static char* obj_op_name(enum obj_operation_type op_type)
}
/*
- * Get a ceph client with specific addr and configuration, if one does
- * not exist create it. Either way, ceph_opts is consumed by this
- * function.
- */
-static struct rbd_client *rbd_get_client(struct ceph_options *ceph_opts)
-{
- struct rbd_client *rbdc;
-
- mutex_lock_nested(&client_mutex, SINGLE_DEPTH_NESTING);
- rbdc = rbd_client_find(ceph_opts);
- if (rbdc) /* using an existing client */
- ceph_destroy_options(ceph_opts);
- else
- rbdc = rbd_client_create(ceph_opts);
- mutex_unlock(&client_mutex);
-
- return rbdc;
-}
-
-/*
* Destroy ceph client
*
* Caller must hold rbd_client_list_lock.
@@ -904,6 +858,56 @@ static void rbd_put_client(struct rbd_client *rbdc)
kref_put(&rbdc->kref, rbd_client_release);
}
+static int wait_for_latest_osdmap(struct ceph_client *client)
+{
+ u64 newest_epoch;
+ int ret;
+
+ ret = ceph_monc_get_version(&client->monc, "osdmap", &newest_epoch);
+ if (ret)
+ return ret;
+
+ if (client->osdc.osdmap->epoch >= newest_epoch)
+ return 0;
+
+ ceph_osdc_maybe_request_map(&client->osdc);
+ return ceph_monc_wait_osdmap(&client->monc, newest_epoch,
+ client->options->mount_timeout);
+}
+
+/*
+ * Get a ceph client with specific addr and configuration, if one does
+ * not exist create it. Either way, ceph_opts is consumed by this
+ * function.
+ */
+static struct rbd_client *rbd_get_client(struct ceph_options *ceph_opts)
+{
+ struct rbd_client *rbdc;
+ int ret;
+
+ mutex_lock_nested(&client_mutex, SINGLE_DEPTH_NESTING);
+ rbdc = rbd_client_find(ceph_opts);
+ if (rbdc) {
+ ceph_destroy_options(ceph_opts);
+
+ /*
+ * Using an existing client. Make sure ->pg_pools is up to
+ * date before we look up the pool id in do_rbd_add().
+ */
+ ret = wait_for_latest_osdmap(rbdc->client);
+ if (ret) {
+ rbd_warn(NULL, "failed to get latest osdmap: %d", ret);
+ rbd_put_client(rbdc);
+ rbdc = ERR_PTR(ret);
+ }
+ } else {
+ rbdc = rbd_client_create(ceph_opts);
+ }
+ mutex_unlock(&client_mutex);
+
+ return rbdc;
+}
+
static bool rbd_image_format_valid(u32 image_format)
{
return image_format == 1 || image_format == 2;
@@ -1223,272 +1227,59 @@ static void rbd_dev_mapping_clear(struct rbd_device *rbd_dev)
rbd_dev->mapping.features = 0;
}
-static u64 rbd_segment_offset(struct rbd_device *rbd_dev, u64 offset)
-{
- u64 segment_size = rbd_obj_bytes(&rbd_dev->header);
-
- return offset & (segment_size - 1);
-}
-
-static u64 rbd_segment_length(struct rbd_device *rbd_dev,
- u64 offset, u64 length)
-{
- u64 segment_size = rbd_obj_bytes(&rbd_dev->header);
-
- offset &= segment_size - 1;
-
- rbd_assert(length <= U64_MAX - offset);
- if (offset + length > segment_size)
- length = segment_size - offset;
-
- return length;
-}
-
-/*
- * bio helpers
- */
-
-static void bio_chain_put(struct bio *chain)
-{
- struct bio *tmp;
-
- while (chain) {
- tmp = chain;
- chain = chain->bi_next;
- bio_put(tmp);
- }
-}
-
-/*
- * zeros a bio chain, starting at specific offset
- */
-static void zero_bio_chain(struct bio *chain, int start_ofs)
+static void zero_bvec(struct bio_vec *bv)
{
- struct bio_vec bv;
- struct bvec_iter iter;
- unsigned long flags;
void *buf;
- int pos = 0;
-
- while (chain) {
- bio_for_each_segment(bv, chain, iter) {
- if (pos + bv.bv_len > start_ofs) {
- int remainder = max(start_ofs - pos, 0);
- buf = bvec_kmap_irq(&bv, &flags);
- memset(buf + remainder, 0,
- bv.bv_len - remainder);
- flush_dcache_page(bv.bv_page);
- bvec_kunmap_irq(buf, &flags);
- }
- pos += bv.bv_len;
- }
+ unsigned long flags;
- chain = chain->bi_next;
- }
+ buf = bvec_kmap_irq(bv, &flags);
+ memset(buf, 0, bv->bv_len);
+ flush_dcache_page(bv->bv_page);
+ bvec_kunmap_irq(buf, &flags);
}
-/*
- * similar to zero_bio_chain(), zeros data defined by a page array,
- * starting at the given byte offset from the start of the array and
- * continuing up to the given end offset. The pages array is
- * assumed to be big enough to hold all bytes up to the end.
- */
-static void zero_pages(struct page **pages, u64 offset, u64 end)
+static void zero_bios(struct ceph_bio_iter *bio_pos, u32 off, u32 bytes)
{
- struct page **page = &pages[offset >> PAGE_SHIFT];
+ struct ceph_bio_iter it = *bio_pos;
- rbd_assert(end > offset);
- rbd_assert(end - offset <= (u64)SIZE_MAX);
- while (offset < end) {
- size_t page_offset;
- size_t length;
- unsigned long flags;
- void *kaddr;
-
- page_offset = offset & ~PAGE_MASK;
- length = min_t(size_t, PAGE_SIZE - page_offset, end - offset);
- local_irq_save(flags);
- kaddr = kmap_atomic(*page);
- memset(kaddr + page_offset, 0, length);
- flush_dcache_page(*page);
- kunmap_atomic(kaddr);
- local_irq_restore(flags);
-
- offset += length;
- page++;
- }
+ ceph_bio_iter_advance(&it, off);
+ ceph_bio_iter_advance_step(&it, bytes, ({
+ zero_bvec(&bv);
+ }));
}
-/*
- * Clone a portion of a bio, starting at the given byte offset
- * and continuing for the number of bytes indicated.
- */
-static struct bio *bio_clone_range(struct bio *bio_src,
- unsigned int offset,
- unsigned int len,
- gfp_t gfpmask)
+static void zero_bvecs(struct ceph_bvec_iter *bvec_pos, u32 off, u32 bytes)
{
- struct bio *bio;
-
- bio = bio_clone_fast(bio_src, gfpmask, rbd_bio_clone);
- if (!bio)
- return NULL; /* ENOMEM */
+ struct ceph_bvec_iter it = *bvec_pos;
- bio_advance(bio, offset);
- bio->bi_iter.bi_size = len;
-
- return bio;
+ ceph_bvec_iter_advance(&it, off);
+ ceph_bvec_iter_advance_step(&it, bytes, ({
+ zero_bvec(&bv);
+ }));
}
/*
- * Clone a portion of a bio chain, starting at the given byte offset
- * into the first bio in the source chain and continuing for the
- * number of bytes indicated. The result is another bio chain of
- * exactly the given length, or a null pointer on error.
- *
- * The bio_src and offset parameters are both in-out. On entry they
- * refer to the first source bio and the offset into that bio where
- * the start of data to be cloned is located.
+ * Zero a range in @obj_req data buffer defined by a bio (list) or
+ * (private) bio_vec array.
*
- * On return, bio_src is updated to refer to the bio in the source
- * chain that contains first un-cloned byte, and *offset will
- * contain the offset of that byte within that bio.
+ * @off is relative to the start of the data buffer.
*/
-static struct bio *bio_chain_clone_range(struct bio **bio_src,
- unsigned int *offset,
- unsigned int len,
- gfp_t gfpmask)
+static void rbd_obj_zero_range(struct rbd_obj_request *obj_req, u32 off,
+ u32 bytes)
{
- struct bio *bi = *bio_src;
- unsigned int off = *offset;
- struct bio *chain = NULL;
- struct bio **end;
-
- /* Build up a chain of clone bios up to the limit */
-
- if (!bi || off >= bi->bi_iter.bi_size || !len)
- return NULL; /* Nothing to clone */
-
- end = &chain;
- while (len) {
- unsigned int bi_size;
- struct bio *bio;
-
- if (!bi) {
- rbd_warn(NULL, "bio_chain exhausted with %u left", len);
- goto out_err; /* EINVAL; ran out of bio's */
- }
- bi_size = min_t(unsigned int, bi->bi_iter.bi_size - off, len);
- bio = bio_clone_range(bi, off, bi_size, gfpmask);
- if (!bio)
- goto out_err; /* ENOMEM */
-
- *end = bio;
- end = &bio->bi_next;
-
- off += bi_size;
- if (off == bi->bi_iter.bi_size) {
- bi = bi->bi_next;
- off = 0;
- }
- len -= bi_size;
- }
- *bio_src = bi;
- *offset = off;
-
- return chain;
-out_err:
- bio_chain_put(chain);
-
- return NULL;
-}
-
-/*
- * The default/initial value for all object request flags is 0. For
- * each flag, once its value is set to 1 it is never reset to 0
- * again.
- */
-static void obj_request_img_data_set(struct rbd_obj_request *obj_request)
-{
- if (test_and_set_bit(OBJ_REQ_IMG_DATA, &obj_request->flags)) {
- struct rbd_device *rbd_dev;
-
- rbd_dev = obj_request->img_request->rbd_dev;
- rbd_warn(rbd_dev, "obj_request %p already marked img_data",
- obj_request);
- }
-}
-
-static bool obj_request_img_data_test(struct rbd_obj_request *obj_request)
-{
- smp_mb();
- return test_bit(OBJ_REQ_IMG_DATA, &obj_request->flags) != 0;
-}
-
-static void obj_request_done_set(struct rbd_obj_request *obj_request)
-{
- if (test_and_set_bit(OBJ_REQ_DONE, &obj_request->flags)) {
- struct rbd_device *rbd_dev = NULL;
-
- if (obj_request_img_data_test(obj_request))
- rbd_dev = obj_request->img_request->rbd_dev;
- rbd_warn(rbd_dev, "obj_request %p already marked done",
- obj_request);
+ switch (obj_req->img_request->data_type) {
+ case OBJ_REQUEST_BIO:
+ zero_bios(&obj_req->bio_pos, off, bytes);
+ break;
+ case OBJ_REQUEST_BVECS:
+ case OBJ_REQUEST_OWN_BVECS:
+ zero_bvecs(&obj_req->bvec_pos, off, bytes);
+ break;
+ default:
+ rbd_assert(0);
}
}
-static bool obj_request_done_test(struct rbd_obj_request *obj_request)
-{
- smp_mb();
- return test_bit(OBJ_REQ_DONE, &obj_request->flags) != 0;
-}
-
-/*
- * This sets the KNOWN flag after (possibly) setting the EXISTS
- * flag. The latter is set based on the "exists" value provided.
- *
- * Note that for our purposes once an object exists it never goes
- * away again. It's possible that the response from two existence
- * checks are separated by the creation of the target object, and
- * the first ("doesn't exist") response arrives *after* the second
- * ("does exist"). In that case we ignore the second one.
- */
-static void obj_request_existence_set(struct rbd_obj_request *obj_request,
- bool exists)
-{
- if (exists)
- set_bit(OBJ_REQ_EXISTS, &obj_request->flags);
- set_bit(OBJ_REQ_KNOWN, &obj_request->flags);
- smp_mb();
-}
-
-static bool obj_request_known_test(struct rbd_obj_request *obj_request)
-{
- smp_mb();
- return test_bit(OBJ_REQ_KNOWN, &obj_request->flags) != 0;
-}
-
-static bool obj_request_exists_test(struct rbd_obj_request *obj_request)
-{
- smp_mb();
- return test_bit(OBJ_REQ_EXISTS, &obj_request->flags) != 0;
-}
-
-static bool obj_request_overlaps_parent(struct rbd_obj_request *obj_request)
-{
- struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev;
-
- return obj_request->img_offset <
- round_up(rbd_dev->parent_overlap, rbd_obj_bytes(&rbd_dev->header));
-}
-
-static void rbd_obj_request_get(struct rbd_obj_request *obj_request)
-{
- dout("%s: obj %p (was %d)\n", __func__, obj_request,
- kref_read(&obj_request->kref));
- kref_get(&obj_request->kref);
-}
-
static void rbd_obj_request_destroy(struct kref *kref);
static void rbd_obj_request_put(struct rbd_obj_request *obj_request)
{
@@ -1505,18 +1296,13 @@ static void rbd_img_request_get(struct rbd_img_request *img_request)
kref_get(&img_request->kref);
}
-static bool img_request_child_test(struct rbd_img_request *img_request);
-static void rbd_parent_request_destroy(struct kref *kref);
static void rbd_img_request_destroy(struct kref *kref);
static void rbd_img_request_put(struct rbd_img_request *img_request)
{
rbd_assert(img_request != NULL);
dout("%s: img %p (was %d)\n", __func__, img_request,
kref_read(&img_request->kref));
- if (img_request_child_test(img_request))
- kref_put(&img_request->kref, rbd_parent_request_destroy);
- else
- kref_put(&img_request->kref, rbd_img_request_destroy);
+ kref_put(&img_request->kref, rbd_img_request_destroy);
}
static inline void rbd_img_obj_request_add(struct rbd_img_request *img_request,
@@ -1526,139 +1312,37 @@ static inline void rbd_img_obj_request_add(struct rbd_img_request *img_request,
/* Image request now owns object's original reference */
obj_request->img_request = img_request;
- obj_request->which = img_request->obj_request_count;
- rbd_assert(!obj_request_img_data_test(obj_request));
- obj_request_img_data_set(obj_request);
- rbd_assert(obj_request->which != BAD_WHICH);
img_request->obj_request_count++;
- list_add_tail(&obj_request->links, &img_request->obj_requests);
- dout("%s: img %p obj %p w=%u\n", __func__, img_request, obj_request,
- obj_request->which);
+ img_request->pending_count++;
+ dout("%s: img %p obj %p\n", __func__, img_request, obj_request);
}
static inline void rbd_img_obj_request_del(struct rbd_img_request *img_request,
struct rbd_obj_request *obj_request)
{
- rbd_assert(obj_request->which != BAD_WHICH);
-
- dout("%s: img %p obj %p w=%u\n", __func__, img_request, obj_request,
- obj_request->which);
- list_del(&obj_request->links);
+ dout("%s: img %p obj %p\n", __func__, img_request, obj_request);
+ list_del(&obj_request->ex.oe_item);
rbd_assert(img_request->obj_request_count > 0);
img_request->obj_request_count--;
- rbd_assert(obj_request->which == img_request->obj_request_count);
- obj_request->which = BAD_WHICH;
- rbd_assert(obj_request_img_data_test(obj_request));
rbd_assert(obj_request->img_request == img_request);
- obj_request->img_request = NULL;
- obj_request->callback = NULL;
rbd_obj_request_put(obj_request);
}
-static bool obj_request_type_valid(enum obj_request_type type)
-{
- switch (type) {
- case OBJ_REQUEST_NODATA:
- case OBJ_REQUEST_BIO:
- case OBJ_REQUEST_PAGES:
- return true;
- default:
- return false;
- }
-}
-
-static void rbd_img_obj_callback(struct rbd_obj_request *obj_request);
-
static void rbd_obj_request_submit(struct rbd_obj_request *obj_request)
{
struct ceph_osd_request *osd_req = obj_request->osd_req;
dout("%s %p object_no %016llx %llu~%llu osd_req %p\n", __func__,
- obj_request, obj_request->object_no, obj_request->offset,
- obj_request->length, osd_req);
- if (obj_request_img_data_test(obj_request)) {
- WARN_ON(obj_request->callback != rbd_img_obj_callback);
- rbd_img_request_get(obj_request->img_request);
- }
+ obj_request, obj_request->ex.oe_objno, obj_request->ex.oe_off,
+ obj_request->ex.oe_len, osd_req);
ceph_osdc_start_request(osd_req->r_osdc, osd_req, false);
}
-static void rbd_img_request_complete(struct rbd_img_request *img_request)
-{
-
- dout("%s: img %p\n", __func__, img_request);
-
- /*
- * If no error occurred, compute the aggregate transfer
- * count for the image request. We could instead use
- * atomic64_cmpxchg() to update it as each object request
- * completes; not clear which way is better off hand.
- */
- if (!img_request->result) {
- struct rbd_obj_request *obj_request;
- u64 xferred = 0;
-
- for_each_obj_request(img_request, obj_request)
- xferred += obj_request->xferred;
- img_request->xferred = xferred;
- }
-
- if (img_request->callback)
- img_request->callback(img_request);
- else
- rbd_img_request_put(img_request);
-}
-
/*
* The default/initial value for all image request flags is 0. Each
* is conditionally set to 1 at image request initialization time
* and currently never change thereafter.
*/
-static void img_request_write_set(struct rbd_img_request *img_request)
-{
- set_bit(IMG_REQ_WRITE, &img_request->flags);
- smp_mb();
-}
-
-static bool img_request_write_test(struct rbd_img_request *img_request)
-{
- smp_mb();
- return test_bit(IMG_REQ_WRITE, &img_request->flags) != 0;
-}
-
-/*
- * Set the discard flag when the img_request is an discard request
- */
-static void img_request_discard_set(struct rbd_img_request *img_request)
-{
- set_bit(IMG_REQ_DISCARD, &img_request->flags);
- smp_mb();
-}
-
-static bool img_request_discard_test(struct rbd_img_request *img_request)
-{
- smp_mb();
- return test_bit(IMG_REQ_DISCARD, &img_request->flags) != 0;
-}
-
-static void img_request_child_set(struct rbd_img_request *img_request)
-{
- set_bit(IMG_REQ_CHILD, &img_request->flags);
- smp_mb();
-}
-
-static void img_request_child_clear(struct rbd_img_request *img_request)
-{
- clear_bit(IMG_REQ_CHILD, &img_request->flags);
- smp_mb();
-}
-
-static bool img_request_child_test(struct rbd_img_request *img_request)
-{
- smp_mb();
- return test_bit(IMG_REQ_CHILD, &img_request->flags) != 0;
-}
-
static void img_request_layered_set(struct rbd_img_request *img_request)
{
set_bit(IMG_REQ_LAYERED, &img_request->flags);
@@ -1677,209 +1361,70 @@ static bool img_request_layered_test(struct rbd_img_request *img_request)
return test_bit(IMG_REQ_LAYERED, &img_request->flags) != 0;
}
-static enum obj_operation_type
-rbd_img_request_op_type(struct rbd_img_request *img_request)
-{
- if (img_request_write_test(img_request))
- return OBJ_OP_WRITE;
- else if (img_request_discard_test(img_request))
- return OBJ_OP_DISCARD;
- else
- return OBJ_OP_READ;
-}
-
-static void
-rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request)
-{
- u64 xferred = obj_request->xferred;
- u64 length = obj_request->length;
-
- dout("%s: obj %p img %p result %d %llu/%llu\n", __func__,
- obj_request, obj_request->img_request, obj_request->result,
- xferred, length);
- /*
- * ENOENT means a hole in the image. We zero-fill the entire
- * length of the request. A short read also implies zero-fill
- * to the end of the request. An error requires the whole
- * length of the request to be reported finished with an error
- * to the block layer. In each case we update the xferred
- * count to indicate the whole request was satisfied.
- */
- rbd_assert(obj_request->type != OBJ_REQUEST_NODATA);
- if (obj_request->result == -ENOENT) {
- if (obj_request->type == OBJ_REQUEST_BIO)
- zero_bio_chain(obj_request->bio_list, 0);
- else
- zero_pages(obj_request->pages, 0, length);
- obj_request->result = 0;
- } else if (xferred < length && !obj_request->result) {
- if (obj_request->type == OBJ_REQUEST_BIO)
- zero_bio_chain(obj_request->bio_list, xferred);
- else
- zero_pages(obj_request->pages, xferred, length);
- }
- obj_request->xferred = length;
- obj_request_done_set(obj_request);
-}
-
-static void rbd_obj_request_complete(struct rbd_obj_request *obj_request)
+static bool rbd_obj_is_entire(struct rbd_obj_request *obj_req)
{
- dout("%s: obj %p cb %p\n", __func__, obj_request,
- obj_request->callback);
- obj_request->callback(obj_request);
-}
+ struct rbd_device *rbd_dev = obj_req->img_request->rbd_dev;
-static void rbd_obj_request_error(struct rbd_obj_request *obj_request, int err)
-{
- obj_request->result = err;
- obj_request->xferred = 0;
- /*
- * kludge - mirror rbd_obj_request_submit() to match a put in
- * rbd_img_obj_callback()
- */
- if (obj_request_img_data_test(obj_request)) {
- WARN_ON(obj_request->callback != rbd_img_obj_callback);
- rbd_img_request_get(obj_request->img_request);
- }
- obj_request_done_set(obj_request);
- rbd_obj_request_complete(obj_request);
+ return !obj_req->ex.oe_off &&
+ obj_req->ex.oe_len == rbd_dev->layout.object_size;
}
-static void rbd_osd_read_callback(struct rbd_obj_request *obj_request)
+static bool rbd_obj_is_tail(struct rbd_obj_request *obj_req)
{
- struct rbd_img_request *img_request = NULL;
- struct rbd_device *rbd_dev = NULL;
- bool layered = false;
-
- if (obj_request_img_data_test(obj_request)) {
- img_request = obj_request->img_request;
- layered = img_request && img_request_layered_test(img_request);
- rbd_dev = img_request->rbd_dev;
- }
-
- dout("%s: obj %p img %p result %d %llu/%llu\n", __func__,
- obj_request, img_request, obj_request->result,
- obj_request->xferred, obj_request->length);
- if (layered && obj_request->result == -ENOENT &&
- obj_request->img_offset < rbd_dev->parent_overlap)
- rbd_img_parent_read(obj_request);
- else if (img_request)
- rbd_img_obj_request_read_callback(obj_request);
- else
- obj_request_done_set(obj_request);
-}
+ struct rbd_device *rbd_dev = obj_req->img_request->rbd_dev;
-static void rbd_osd_write_callback(struct rbd_obj_request *obj_request)
-{
- dout("%s: obj %p result %d %llu\n", __func__, obj_request,
- obj_request->result, obj_request->length);
- /*
- * There is no such thing as a successful short write. Set
- * it to our originally-requested length.
- */
- obj_request->xferred = obj_request->length;
- obj_request_done_set(obj_request);
+ return obj_req->ex.oe_off + obj_req->ex.oe_len ==
+ rbd_dev->layout.object_size;
}
-static void rbd_osd_discard_callback(struct rbd_obj_request *obj_request)
+static u64 rbd_obj_img_extents_bytes(struct rbd_obj_request *obj_req)
{
- dout("%s: obj %p result %d %llu\n", __func__, obj_request,
- obj_request->result, obj_request->length);
- /*
- * There is no such thing as a successful short discard. Set
- * it to our originally-requested length.
- */
- obj_request->xferred = obj_request->length;
- /* discarding a non-existent object is not a problem */
- if (obj_request->result == -ENOENT)
- obj_request->result = 0;
- obj_request_done_set(obj_request);
+ return ceph_file_extents_bytes(obj_req->img_extents,
+ obj_req->num_img_extents);
}
-/*
- * For a simple stat call there's nothing to do. We'll do more if
- * this is part of a write sequence for a layered image.
- */
-static void rbd_osd_stat_callback(struct rbd_obj_request *obj_request)
+static bool rbd_img_is_write(struct rbd_img_request *img_req)
{
- dout("%s: obj %p\n", __func__, obj_request);
- obj_request_done_set(obj_request);
+ switch (img_req->op_type) {
+ case OBJ_OP_READ:
+ return false;
+ case OBJ_OP_WRITE:
+ case OBJ_OP_DISCARD:
+ return true;
+ default:
+ rbd_assert(0);
+ }
}
-static void rbd_osd_call_callback(struct rbd_obj_request *obj_request)
-{
- dout("%s: obj %p\n", __func__, obj_request);
-
- if (obj_request_img_data_test(obj_request))
- rbd_osd_copyup_callback(obj_request);
- else
- obj_request_done_set(obj_request);
-}
+static void rbd_obj_handle_request(struct rbd_obj_request *obj_req);
static void rbd_osd_req_callback(struct ceph_osd_request *osd_req)
{
- struct rbd_obj_request *obj_request = osd_req->r_priv;
- u16 opcode;
+ struct rbd_obj_request *obj_req = osd_req->r_priv;
- dout("%s: osd_req %p\n", __func__, osd_req);
- rbd_assert(osd_req == obj_request->osd_req);
- if (obj_request_img_data_test(obj_request)) {
- rbd_assert(obj_request->img_request);
- rbd_assert(obj_request->which != BAD_WHICH);
- } else {
- rbd_assert(obj_request->which == BAD_WHICH);
- }
-
- if (osd_req->r_result < 0)
- obj_request->result = osd_req->r_result;
-
- /*
- * We support a 64-bit length, but ultimately it has to be
- * passed to the block layer, which just supports a 32-bit
- * length field.
- */
- obj_request->xferred = osd_req->r_ops[0].outdata_len;
- rbd_assert(obj_request->xferred < (u64)UINT_MAX);
+ dout("%s osd_req %p result %d for obj_req %p\n", __func__, osd_req,
+ osd_req->r_result, obj_req);
+ rbd_assert(osd_req == obj_req->osd_req);
- opcode = osd_req->r_ops[0].op;
- switch (opcode) {
- case CEPH_OSD_OP_READ:
- rbd_osd_read_callback(obj_request);
- break;
- case CEPH_OSD_OP_SETALLOCHINT:
- rbd_assert(osd_req->r_ops[1].op == CEPH_OSD_OP_WRITE ||
- osd_req->r_ops[1].op == CEPH_OSD_OP_WRITEFULL);
- /* fall through */
- case CEPH_OSD_OP_WRITE:
- case CEPH_OSD_OP_WRITEFULL:
- rbd_osd_write_callback(obj_request);
- break;
- case CEPH_OSD_OP_STAT:
- rbd_osd_stat_callback(obj_request);
- break;
- case CEPH_OSD_OP_DELETE:
- case CEPH_OSD_OP_TRUNCATE:
- case CEPH_OSD_OP_ZERO:
- rbd_osd_discard_callback(obj_request);
- break;
- case CEPH_OSD_OP_CALL:
- rbd_osd_call_callback(obj_request);
- break;
- default:
- rbd_warn(NULL, "unexpected OSD op: object_no %016llx opcode %d",
- obj_request->object_no, opcode);
- break;
- }
+ obj_req->result = osd_req->r_result < 0 ? osd_req->r_result : 0;
+ if (!obj_req->result && !rbd_img_is_write(obj_req->img_request))
+ obj_req->xferred = osd_req->r_result;
+ else
+ /*
+ * Writes aren't allowed to return a data payload. In some
+ * guarded write cases (e.g. stat + zero on an empty object)
+ * a stat response makes it through, but we don't care.
+ */
+ obj_req->xferred = 0;
- if (obj_request_done_test(obj_request))
- rbd_obj_request_complete(obj_request);
+ rbd_obj_handle_request(obj_req);
}
static void rbd_osd_req_format_read(struct rbd_obj_request *obj_request)
{
struct ceph_osd_request *osd_req = obj_request->osd_req;
- rbd_assert(obj_request_img_data_test(obj_request));
+ osd_req->r_flags = CEPH_OSD_FLAG_READ;
osd_req->r_snapid = obj_request->img_request->snap_id;
}
@@ -1887,32 +1432,33 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
{
struct ceph_osd_request *osd_req = obj_request->osd_req;
+ osd_req->r_flags = CEPH_OSD_FLAG_WRITE;
ktime_get_real_ts(&osd_req->r_mtime);
- osd_req->r_data_offset = obj_request->offset;
+ osd_req->r_data_offset = obj_request->ex.oe_off;
}
static struct ceph_osd_request *
-__rbd_osd_req_create(struct rbd_device *rbd_dev,
- struct ceph_snap_context *snapc,
- int num_ops, unsigned int flags,
- struct rbd_obj_request *obj_request)
+rbd_osd_req_create(struct rbd_obj_request *obj_req, unsigned int num_ops)
{
+ struct rbd_img_request *img_req = obj_req->img_request;
+ struct rbd_device *rbd_dev = img_req->rbd_dev;
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
struct ceph_osd_request *req;
const char *name_format = rbd_dev->image_format == 1 ?
RBD_V1_DATA_FORMAT : RBD_V2_DATA_FORMAT;
- req = ceph_osdc_alloc_request(osdc, snapc, num_ops, false, GFP_NOIO);
+ req = ceph_osdc_alloc_request(osdc,
+ (rbd_img_is_write(img_req) ? img_req->snapc : NULL),
+ num_ops, false, GFP_NOIO);
if (!req)
return NULL;
- req->r_flags = flags;
req->r_callback = rbd_osd_req_callback;
- req->r_priv = obj_request;
+ req->r_priv = obj_req;
req->r_base_oloc.pool = rbd_dev->layout.pool_id;
if (ceph_oid_aprintf(&req->r_base_oid, GFP_NOIO, name_format,
- rbd_dev->header.object_prefix, obj_request->object_no))
+ rbd_dev->header.object_prefix, obj_req->ex.oe_objno))
goto err_req;
if (ceph_osdc_alloc_messages(req, GFP_NOIO))
@@ -1925,83 +1471,20 @@ err_req:
return NULL;
}
-/*
- * Create an osd request. A read request has one osd op (read).
- * A write request has either one (watch) or two (hint+write) osd ops.
- * (All rbd data writes are prefixed with an allocation hint op, but
- * technically osd watch is a write request, hence this distinction.)
- */
-static struct ceph_osd_request *rbd_osd_req_create(
- struct rbd_device *rbd_dev,
- enum obj_operation_type op_type,
- unsigned int num_ops,
- struct rbd_obj_request *obj_request)
-{
- struct ceph_snap_context *snapc = NULL;
-
- if (obj_request_img_data_test(obj_request) &&
- (op_type == OBJ_OP_DISCARD || op_type == OBJ_OP_WRITE)) {
- struct rbd_img_request *img_request = obj_request->img_request;
- if (op_type == OBJ_OP_WRITE) {
- rbd_assert(img_request_write_test(img_request));
- } else {
- rbd_assert(img_request_discard_test(img_request));
- }
- snapc = img_request->snapc;
- }
-
- rbd_assert(num_ops == 1 || ((op_type == OBJ_OP_WRITE) && num_ops == 2));
-
- return __rbd_osd_req_create(rbd_dev, snapc, num_ops,
- (op_type == OBJ_OP_WRITE || op_type == OBJ_OP_DISCARD) ?
- CEPH_OSD_FLAG_WRITE : CEPH_OSD_FLAG_READ, obj_request);
-}
-
-/*
- * Create a copyup osd request based on the information in the object
- * request supplied. A copyup request has two or three osd ops, a
- * copyup method call, potentially a hint op, and a write or truncate
- * or zero op.
- */
-static struct ceph_osd_request *
-rbd_osd_req_create_copyup(struct rbd_obj_request *obj_request)
-{
- struct rbd_img_request *img_request;
- int num_osd_ops = 3;
-
- rbd_assert(obj_request_img_data_test(obj_request));
- img_request = obj_request->img_request;
- rbd_assert(img_request);
- rbd_assert(img_request_write_test(img_request) ||
- img_request_discard_test(img_request));
-
- if (img_request_discard_test(img_request))
- num_osd_ops = 2;
-
- return __rbd_osd_req_create(img_request->rbd_dev,
- img_request->snapc, num_osd_ops,
- CEPH_OSD_FLAG_WRITE, obj_request);
-}
-
static void rbd_osd_req_destroy(struct ceph_osd_request *osd_req)
{
ceph_osdc_put_request(osd_req);
}
-static struct rbd_obj_request *
-rbd_obj_request_create(enum obj_request_type type)
+static struct rbd_obj_request *rbd_obj_request_create(void)
{
struct rbd_obj_request *obj_request;
- rbd_assert(obj_request_type_valid(type));
-
obj_request = kmem_cache_zalloc(rbd_obj_request_cache, GFP_NOIO);
if (!obj_request)
return NULL;
- obj_request->which = BAD_WHICH;
- obj_request->type = type;
- INIT_LIST_HEAD(&obj_request->links);
+ ceph_object_extent_init(&obj_request->ex);
kref_init(&obj_request->kref);
dout("%s %p\n", __func__, obj_request);
@@ -2011,32 +1494,34 @@ rbd_obj_request_create(enum obj_request_type type)
static void rbd_obj_request_destroy(struct kref *kref)
{
struct rbd_obj_request *obj_request;
+ u32 i;
obj_request = container_of(kref, struct rbd_obj_request, kref);
dout("%s: obj %p\n", __func__, obj_request);
- rbd_assert(obj_request->img_request == NULL);
- rbd_assert(obj_request->which == BAD_WHICH);
-
if (obj_request->osd_req)
rbd_osd_req_destroy(obj_request->osd_req);
- rbd_assert(obj_request_type_valid(obj_request->type));
- switch (obj_request->type) {
+ switch (obj_request->img_request->data_type) {
case OBJ_REQUEST_NODATA:
- break; /* Nothing to do */
case OBJ_REQUEST_BIO:
- if (obj_request->bio_list)
- bio_chain_put(obj_request->bio_list);
- break;
- case OBJ_REQUEST_PAGES:
- /* img_data requests don't own their page array */
- if (obj_request->pages &&
- !obj_request_img_data_test(obj_request))
- ceph_release_page_vector(obj_request->pages,
- obj_request->page_count);
+ case OBJ_REQUEST_BVECS:
+ break; /* Nothing to do */
+ case OBJ_REQUEST_OWN_BVECS:
+ kfree(obj_request->bvec_pos.bvecs);
break;
+ default:
+ rbd_assert(0);
+ }
+
+ kfree(obj_request->img_extents);
+ if (obj_request->copyup_bvecs) {
+ for (i = 0; i < obj_request->copyup_bvec_count; i++) {
+ if (obj_request->copyup_bvecs[i].bv_page)
+ __free_page(obj_request->copyup_bvecs[i].bv_page);
+ }
+ kfree(obj_request->copyup_bvecs);
}
kmem_cache_free(rbd_obj_request_cache, obj_request);
@@ -2111,7 +1596,6 @@ static bool rbd_dev_parent_get(struct rbd_device *rbd_dev)
*/
static struct rbd_img_request *rbd_img_request_create(
struct rbd_device *rbd_dev,
- u64 offset, u64 length,
enum obj_operation_type op_type,
struct ceph_snap_context *snapc)
{
@@ -2122,27 +1606,21 @@ static struct rbd_img_request *rbd_img_request_create(
return NULL;
img_request->rbd_dev = rbd_dev;
- img_request->offset = offset;
- img_request->length = length;
- if (op_type == OBJ_OP_DISCARD) {
- img_request_discard_set(img_request);
- img_request->snapc = snapc;
- } else if (op_type == OBJ_OP_WRITE) {
- img_request_write_set(img_request);
- img_request->snapc = snapc;
- } else {
+ img_request->op_type = op_type;
+ if (!rbd_img_is_write(img_request))
img_request->snap_id = rbd_dev->spec->snap_id;
- }
+ else
+ img_request->snapc = snapc;
+
if (rbd_dev_parent_get(rbd_dev))
img_request_layered_set(img_request);
spin_lock_init(&img_request->completion_lock);
- INIT_LIST_HEAD(&img_request->obj_requests);
+ INIT_LIST_HEAD(&img_request->object_extents);
kref_init(&img_request->kref);
- dout("%s: rbd_dev %p %s %llu/%llu -> img %p\n", __func__, rbd_dev,
- obj_op_name(op_type), offset, length, img_request);
-
+ dout("%s: rbd_dev %p %s -> img %p\n", __func__, rbd_dev,
+ obj_op_name(op_type), img_request);
return img_request;
}
@@ -2165,829 +1643,934 @@ static void rbd_img_request_destroy(struct kref *kref)
rbd_dev_parent_put(img_request->rbd_dev);
}
- if (img_request_write_test(img_request) ||
- img_request_discard_test(img_request))
+ if (rbd_img_is_write(img_request))
ceph_put_snap_context(img_request->snapc);
kmem_cache_free(rbd_img_request_cache, img_request);
}
-static struct rbd_img_request *rbd_parent_request_create(
- struct rbd_obj_request *obj_request,
- u64 img_offset, u64 length)
+static void prune_extents(struct ceph_file_extent *img_extents,
+ u32 *num_img_extents, u64 overlap)
{
- struct rbd_img_request *parent_request;
- struct rbd_device *rbd_dev;
+ u32 cnt = *num_img_extents;
- rbd_assert(obj_request->img_request);
- rbd_dev = obj_request->img_request->rbd_dev;
+ /* drop extents completely beyond the overlap */
+ while (cnt && img_extents[cnt - 1].fe_off >= overlap)
+ cnt--;
- parent_request = rbd_img_request_create(rbd_dev->parent, img_offset,
- length, OBJ_OP_READ, NULL);
- if (!parent_request)
- return NULL;
+ if (cnt) {
+ struct ceph_file_extent *ex = &img_extents[cnt - 1];
- img_request_child_set(parent_request);
- rbd_obj_request_get(obj_request);
- parent_request->obj_request = obj_request;
+ /* trim final overlapping extent */
+ if (ex->fe_off + ex->fe_len > overlap)
+ ex->fe_len = overlap - ex->fe_off;
+ }
- return parent_request;
+ *num_img_extents = cnt;
}
-static void rbd_parent_request_destroy(struct kref *kref)
+/*
+ * Determine the byte range(s) covered by either just the object extent
+ * or the entire object in the parent image.
+ */
+static int rbd_obj_calc_img_extents(struct rbd_obj_request *obj_req,
+ bool entire)
{
- struct rbd_img_request *parent_request;
- struct rbd_obj_request *orig_request;
+ struct rbd_device *rbd_dev = obj_req->img_request->rbd_dev;
+ int ret;
- parent_request = container_of(kref, struct rbd_img_request, kref);
- orig_request = parent_request->obj_request;
+ if (!rbd_dev->parent_overlap)
+ return 0;
- parent_request->obj_request = NULL;
- rbd_obj_request_put(orig_request);
- img_request_child_clear(parent_request);
+ ret = ceph_extent_to_file(&rbd_dev->layout, obj_req->ex.oe_objno,
+ entire ? 0 : obj_req->ex.oe_off,
+ entire ? rbd_dev->layout.object_size :
+ obj_req->ex.oe_len,
+ &obj_req->img_extents,
+ &obj_req->num_img_extents);
+ if (ret)
+ return ret;
- rbd_img_request_destroy(kref);
+ prune_extents(obj_req->img_extents, &obj_req->num_img_extents,
+ rbd_dev->parent_overlap);
+ return 0;
}
-static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request)
+static void rbd_osd_req_setup_data(struct rbd_obj_request *obj_req, u32 which)
{
- struct rbd_img_request *img_request;
- unsigned int xferred;
- int result;
- bool more;
-
- rbd_assert(obj_request_img_data_test(obj_request));
- img_request = obj_request->img_request;
-
- rbd_assert(obj_request->xferred <= (u64)UINT_MAX);
- xferred = (unsigned int)obj_request->xferred;
- result = obj_request->result;
- if (result) {
- struct rbd_device *rbd_dev = img_request->rbd_dev;
- enum obj_operation_type op_type;
-
- if (img_request_discard_test(img_request))
- op_type = OBJ_OP_DISCARD;
- else if (img_request_write_test(img_request))
- op_type = OBJ_OP_WRITE;
- else
- op_type = OBJ_OP_READ;
-
- rbd_warn(rbd_dev, "%s %llx at %llx (%llx)",
- obj_op_name(op_type), obj_request->length,
- obj_request->img_offset, obj_request->offset);
- rbd_warn(rbd_dev, " result %d xferred %x",
- result, xferred);
- if (!img_request->result)
- img_request->result = result;
- /*
- * Need to end I/O on the entire obj_request worth of
- * bytes in case of error.
- */
- xferred = obj_request->length;
+ switch (obj_req->img_request->data_type) {
+ case OBJ_REQUEST_BIO:
+ osd_req_op_extent_osd_data_bio(obj_req->osd_req, which,
+ &obj_req->bio_pos,
+ obj_req->ex.oe_len);
+ break;
+ case OBJ_REQUEST_BVECS:
+ case OBJ_REQUEST_OWN_BVECS:
+ rbd_assert(obj_req->bvec_pos.iter.bi_size ==
+ obj_req->ex.oe_len);
+ rbd_assert(obj_req->bvec_idx == obj_req->bvec_count);
+ osd_req_op_extent_osd_data_bvec_pos(obj_req->osd_req, which,
+ &obj_req->bvec_pos);
+ break;
+ default:
+ rbd_assert(0);
}
+}
- if (img_request_child_test(img_request)) {
- rbd_assert(img_request->obj_request != NULL);
- more = obj_request->which < img_request->obj_request_count - 1;
- } else {
- blk_status_t status = errno_to_blk_status(result);
+static int rbd_obj_setup_read(struct rbd_obj_request *obj_req)
+{
+ obj_req->osd_req = rbd_osd_req_create(obj_req, 1);
+ if (!obj_req->osd_req)
+ return -ENOMEM;
- rbd_assert(img_request->rq != NULL);
+ osd_req_op_extent_init(obj_req->osd_req, 0, CEPH_OSD_OP_READ,
+ obj_req->ex.oe_off, obj_req->ex.oe_len, 0, 0);
+ rbd_osd_req_setup_data(obj_req, 0);
- more = blk_update_request(img_request->rq, status, xferred);
- if (!more)
- __blk_mq_end_request(img_request->rq, status);
- }
+ rbd_osd_req_format_read(obj_req);
+ return 0;
+}
+
+static int __rbd_obj_setup_stat(struct rbd_obj_request *obj_req,
+ unsigned int which)
+{
+ struct page **pages;
- return more;
+ /*
+ * The response data for a STAT call consists of:
+ * le64 length;
+ * struct {
+ * le32 tv_sec;
+ * le32 tv_nsec;
+ * } mtime;
+ */
+ pages = ceph_alloc_page_vector(1, GFP_NOIO);
+ if (IS_ERR(pages))
+ return PTR_ERR(pages);
+
+ osd_req_op_init(obj_req->osd_req, which, CEPH_OSD_OP_STAT, 0);
+ osd_req_op_raw_data_in_pages(obj_req->osd_req, which, pages,
+ 8 + sizeof(struct ceph_timespec),
+ 0, false, true);
+ return 0;
}
-static void rbd_img_obj_callback(struct rbd_obj_request *obj_request)
+static void __rbd_obj_setup_write(struct rbd_obj_request *obj_req,
+ unsigned int which)
{
- struct rbd_img_request *img_request;
- u32 which = obj_request->which;
- bool more = true;
+ struct rbd_device *rbd_dev = obj_req->img_request->rbd_dev;
+ u16 opcode;
- rbd_assert(obj_request_img_data_test(obj_request));
- img_request = obj_request->img_request;
+ osd_req_op_alloc_hint_init(obj_req->osd_req, which++,
+ rbd_dev->layout.object_size,
+ rbd_dev->layout.object_size);
- dout("%s: img %p obj %p\n", __func__, img_request, obj_request);
- rbd_assert(img_request != NULL);
- rbd_assert(img_request->obj_request_count > 0);
- rbd_assert(which != BAD_WHICH);
- rbd_assert(which < img_request->obj_request_count);
+ if (rbd_obj_is_entire(obj_req))
+ opcode = CEPH_OSD_OP_WRITEFULL;
+ else
+ opcode = CEPH_OSD_OP_WRITE;
- spin_lock_irq(&img_request->completion_lock);
- if (which != img_request->next_completion)
- goto out;
+ osd_req_op_extent_init(obj_req->osd_req, which, opcode,
+ obj_req->ex.oe_off, obj_req->ex.oe_len, 0, 0);
+ rbd_osd_req_setup_data(obj_req, which++);
+
+ rbd_assert(which == obj_req->osd_req->r_num_ops);
+ rbd_osd_req_format_write(obj_req);
+}
- for_each_obj_request_from(img_request, obj_request) {
- rbd_assert(more);
- rbd_assert(which < img_request->obj_request_count);
+static int rbd_obj_setup_write(struct rbd_obj_request *obj_req)
+{
+ unsigned int num_osd_ops, which = 0;
+ int ret;
- if (!obj_request_done_test(obj_request))
- break;
- more = rbd_img_obj_end_request(obj_request);
- which++;
+ /* reverse map the entire object onto the parent */
+ ret = rbd_obj_calc_img_extents(obj_req, true);
+ if (ret)
+ return ret;
+
+ if (obj_req->num_img_extents) {
+ obj_req->write_state = RBD_OBJ_WRITE_GUARD;
+ num_osd_ops = 3; /* stat + setallochint + write/writefull */
+ } else {
+ obj_req->write_state = RBD_OBJ_WRITE_FLAT;
+ num_osd_ops = 2; /* setallochint + write/writefull */
}
- rbd_assert(more ^ (which == img_request->obj_request_count));
- img_request->next_completion = which;
-out:
- spin_unlock_irq(&img_request->completion_lock);
- rbd_img_request_put(img_request);
+ obj_req->osd_req = rbd_osd_req_create(obj_req, num_osd_ops);
+ if (!obj_req->osd_req)
+ return -ENOMEM;
- if (!more)
- rbd_img_request_complete(img_request);
+ if (obj_req->num_img_extents) {
+ ret = __rbd_obj_setup_stat(obj_req, which++);
+ if (ret)
+ return ret;
+ }
+
+ __rbd_obj_setup_write(obj_req, which);
+ return 0;
}
-/*
- * Add individual osd ops to the given ceph_osd_request and prepare
- * them for submission. num_ops is the current number of
- * osd operations already to the object request.
- */
-static void rbd_img_obj_request_fill(struct rbd_obj_request *obj_request,
- struct ceph_osd_request *osd_request,
- enum obj_operation_type op_type,
- unsigned int num_ops)
-{
- struct rbd_img_request *img_request = obj_request->img_request;
- struct rbd_device *rbd_dev = img_request->rbd_dev;
- u64 object_size = rbd_obj_bytes(&rbd_dev->header);
- u64 offset = obj_request->offset;
- u64 length = obj_request->length;
- u64 img_end;
+static void __rbd_obj_setup_discard(struct rbd_obj_request *obj_req,
+ unsigned int which)
+{
u16 opcode;
- if (op_type == OBJ_OP_DISCARD) {
- if (!offset && length == object_size &&
- (!img_request_layered_test(img_request) ||
- !obj_request_overlaps_parent(obj_request))) {
- opcode = CEPH_OSD_OP_DELETE;
- } else if ((offset + length == object_size)) {
+ if (rbd_obj_is_entire(obj_req)) {
+ if (obj_req->num_img_extents) {
+ osd_req_op_init(obj_req->osd_req, which++,
+ CEPH_OSD_OP_CREATE, 0);
opcode = CEPH_OSD_OP_TRUNCATE;
} else {
- down_read(&rbd_dev->header_rwsem);
- img_end = rbd_dev->header.image_size;
- up_read(&rbd_dev->header_rwsem);
-
- if (obj_request->img_offset + length == img_end)
- opcode = CEPH_OSD_OP_TRUNCATE;
- else
- opcode = CEPH_OSD_OP_ZERO;
+ osd_req_op_init(obj_req->osd_req, which++,
+ CEPH_OSD_OP_DELETE, 0);
+ opcode = 0;
}
- } else if (op_type == OBJ_OP_WRITE) {
- if (!offset && length == object_size)
- opcode = CEPH_OSD_OP_WRITEFULL;
- else
- opcode = CEPH_OSD_OP_WRITE;
- osd_req_op_alloc_hint_init(osd_request, num_ops,
- object_size, object_size);
- num_ops++;
+ } else if (rbd_obj_is_tail(obj_req)) {
+ opcode = CEPH_OSD_OP_TRUNCATE;
} else {
- opcode = CEPH_OSD_OP_READ;
+ opcode = CEPH_OSD_OP_ZERO;
}
- if (opcode == CEPH_OSD_OP_DELETE)
- osd_req_op_init(osd_request, num_ops, opcode, 0);
- else
- osd_req_op_extent_init(osd_request, num_ops, opcode,
- offset, length, 0, 0);
-
- if (obj_request->type == OBJ_REQUEST_BIO)
- osd_req_op_extent_osd_data_bio(osd_request, num_ops,
- obj_request->bio_list, length);
- else if (obj_request->type == OBJ_REQUEST_PAGES)
- osd_req_op_extent_osd_data_pages(osd_request, num_ops,
- obj_request->pages, length,
- offset & ~PAGE_MASK, false, false);
-
- /* Discards are also writes */
- if (op_type == OBJ_OP_WRITE || op_type == OBJ_OP_DISCARD)
- rbd_osd_req_format_write(obj_request);
- else
- rbd_osd_req_format_read(obj_request);
+ if (opcode)
+ osd_req_op_extent_init(obj_req->osd_req, which++, opcode,
+ obj_req->ex.oe_off, obj_req->ex.oe_len,
+ 0, 0);
+
+ rbd_assert(which == obj_req->osd_req->r_num_ops);
+ rbd_osd_req_format_write(obj_req);
}
-/*
- * Split up an image request into one or more object requests, each
- * to a different object. The "type" parameter indicates whether
- * "data_desc" is the pointer to the head of a list of bio
- * structures, or the base of a page array. In either case this
- * function assumes data_desc describes memory sufficient to hold
- * all data described by the image request.
- */
-static int rbd_img_request_fill(struct rbd_img_request *img_request,
- enum obj_request_type type,
- void *data_desc)
+static int rbd_obj_setup_discard(struct rbd_obj_request *obj_req)
{
- struct rbd_device *rbd_dev = img_request->rbd_dev;
- struct rbd_obj_request *obj_request = NULL;
- struct rbd_obj_request *next_obj_request;
- struct bio *bio_list = NULL;
- unsigned int bio_offset = 0;
- struct page **pages = NULL;
- enum obj_operation_type op_type;
- u64 img_offset;
- u64 resid;
-
- dout("%s: img %p type %d data_desc %p\n", __func__, img_request,
- (int)type, data_desc);
+ unsigned int num_osd_ops, which = 0;
+ int ret;
- img_offset = img_request->offset;
- resid = img_request->length;
- rbd_assert(resid > 0);
- op_type = rbd_img_request_op_type(img_request);
+ /* reverse map the entire object onto the parent */
+ ret = rbd_obj_calc_img_extents(obj_req, true);
+ if (ret)
+ return ret;
- if (type == OBJ_REQUEST_BIO) {
- bio_list = data_desc;
- rbd_assert(img_offset ==
- bio_list->bi_iter.bi_sector << SECTOR_SHIFT);
- } else if (type == OBJ_REQUEST_PAGES) {
- pages = data_desc;
+ if (rbd_obj_is_entire(obj_req)) {
+ obj_req->write_state = RBD_OBJ_WRITE_FLAT;
+ if (obj_req->num_img_extents)
+ num_osd_ops = 2; /* create + truncate */
+ else
+ num_osd_ops = 1; /* delete */
+ } else {
+ if (obj_req->num_img_extents) {
+ obj_req->write_state = RBD_OBJ_WRITE_GUARD;
+ num_osd_ops = 2; /* stat + truncate/zero */
+ } else {
+ obj_req->write_state = RBD_OBJ_WRITE_FLAT;
+ num_osd_ops = 1; /* truncate/zero */
+ }
}
- while (resid) {
- struct ceph_osd_request *osd_req;
- u64 object_no = img_offset >> rbd_dev->header.obj_order;
- u64 offset = rbd_segment_offset(rbd_dev, img_offset);
- u64 length = rbd_segment_length(rbd_dev, img_offset, resid);
-
- obj_request = rbd_obj_request_create(type);
- if (!obj_request)
- goto out_unwind;
-
- obj_request->object_no = object_no;
- obj_request->offset = offset;
- obj_request->length = length;
-
- /*
- * set obj_request->img_request before creating the
- * osd_request so that it gets the right snapc
- */
- rbd_img_obj_request_add(img_request, obj_request);
-
- if (type == OBJ_REQUEST_BIO) {
- unsigned int clone_size;
-
- rbd_assert(length <= (u64)UINT_MAX);
- clone_size = (unsigned int)length;
- obj_request->bio_list =
- bio_chain_clone_range(&bio_list,
- &bio_offset,
- clone_size,
- GFP_NOIO);
- if (!obj_request->bio_list)
- goto out_unwind;
- } else if (type == OBJ_REQUEST_PAGES) {
- unsigned int page_count;
-
- obj_request->pages = pages;
- page_count = (u32)calc_pages_for(offset, length);
- obj_request->page_count = page_count;
- if ((offset + length) & ~PAGE_MASK)
- page_count--; /* more on last page */
- pages += page_count;
- }
+ obj_req->osd_req = rbd_osd_req_create(obj_req, num_osd_ops);
+ if (!obj_req->osd_req)
+ return -ENOMEM;
- osd_req = rbd_osd_req_create(rbd_dev, op_type,
- (op_type == OBJ_OP_WRITE) ? 2 : 1,
- obj_request);
- if (!osd_req)
- goto out_unwind;
+ if (!rbd_obj_is_entire(obj_req) && obj_req->num_img_extents) {
+ ret = __rbd_obj_setup_stat(obj_req, which++);
+ if (ret)
+ return ret;
+ }
- obj_request->osd_req = osd_req;
- obj_request->callback = rbd_img_obj_callback;
- obj_request->img_offset = img_offset;
+ __rbd_obj_setup_discard(obj_req, which);
+ return 0;
+}
- rbd_img_obj_request_fill(obj_request, osd_req, op_type, 0);
+/*
+ * For each object request in @img_req, allocate an OSD request, add
+ * individual OSD ops and prepare them for submission. The number of
+ * OSD ops depends on op_type and the overlap point (if any).
+ */
+static int __rbd_img_fill_request(struct rbd_img_request *img_req)
+{
+ struct rbd_obj_request *obj_req;
+ int ret;
- img_offset += length;
- resid -= length;
+ for_each_obj_request(img_req, obj_req) {
+ switch (img_req->op_type) {
+ case OBJ_OP_READ:
+ ret = rbd_obj_setup_read(obj_req);
+ break;
+ case OBJ_OP_WRITE:
+ ret = rbd_obj_setup_write(obj_req);
+ break;
+ case OBJ_OP_DISCARD:
+ ret = rbd_obj_setup_discard(obj_req);
+ break;
+ default:
+ rbd_assert(0);
+ }
+ if (ret)
+ return ret;
}
return 0;
+}
-out_unwind:
- for_each_obj_request_safe(img_request, obj_request, next_obj_request)
- rbd_img_obj_request_del(img_request, obj_request);
+union rbd_img_fill_iter {
+ struct ceph_bio_iter bio_iter;
+ struct ceph_bvec_iter bvec_iter;
+};
- return -ENOMEM;
-}
+struct rbd_img_fill_ctx {
+ enum obj_request_type pos_type;
+ union rbd_img_fill_iter *pos;
+ union rbd_img_fill_iter iter;
+ ceph_object_extent_fn_t set_pos_fn;
+ ceph_object_extent_fn_t count_fn;
+ ceph_object_extent_fn_t copy_fn;
+};
-static void
-rbd_osd_copyup_callback(struct rbd_obj_request *obj_request)
+static struct ceph_object_extent *alloc_object_extent(void *arg)
{
- struct rbd_img_request *img_request;
- struct rbd_device *rbd_dev;
- struct page **pages;
- u32 page_count;
+ struct rbd_img_request *img_req = arg;
+ struct rbd_obj_request *obj_req;
- dout("%s: obj %p\n", __func__, obj_request);
+ obj_req = rbd_obj_request_create();
+ if (!obj_req)
+ return NULL;
- rbd_assert(obj_request->type == OBJ_REQUEST_BIO ||
- obj_request->type == OBJ_REQUEST_NODATA);
- rbd_assert(obj_request_img_data_test(obj_request));
- img_request = obj_request->img_request;
- rbd_assert(img_request);
+ rbd_img_obj_request_add(img_req, obj_req);
+ return &obj_req->ex;
+}
- rbd_dev = img_request->rbd_dev;
- rbd_assert(rbd_dev);
+/*
+ * While su != os && sc == 1 is technically not fancy (it's the same
+ * layout as su == os && sc == 1), we can't use the nocopy path for it
+ * because ->set_pos_fn() should be called only once per object.
+ * ceph_file_to_extents() invokes action_fn once per stripe unit, so
+ * treat su != os && sc == 1 as fancy.
+ */
+static bool rbd_layout_is_fancy(struct ceph_file_layout *l)
+{
+ return l->stripe_unit != l->object_size;
+}
- pages = obj_request->copyup_pages;
- rbd_assert(pages != NULL);
- obj_request->copyup_pages = NULL;
- page_count = obj_request->copyup_page_count;
- rbd_assert(page_count);
- obj_request->copyup_page_count = 0;
- ceph_release_page_vector(pages, page_count);
+static int rbd_img_fill_request_nocopy(struct rbd_img_request *img_req,
+ struct ceph_file_extent *img_extents,
+ u32 num_img_extents,
+ struct rbd_img_fill_ctx *fctx)
+{
+ u32 i;
+ int ret;
+
+ img_req->data_type = fctx->pos_type;
/*
- * We want the transfer count to reflect the size of the
- * original write request. There is no such thing as a
- * successful short write, so if the request was successful
- * we can just set it to the originally-requested length.
+ * Create object requests and set each object request's starting
+ * position in the provided bio (list) or bio_vec array.
*/
- if (!obj_request->result)
- obj_request->xferred = obj_request->length;
+ fctx->iter = *fctx->pos;
+ for (i = 0; i < num_img_extents; i++) {
+ ret = ceph_file_to_extents(&img_req->rbd_dev->layout,
+ img_extents[i].fe_off,
+ img_extents[i].fe_len,
+ &img_req->object_extents,
+ alloc_object_extent, img_req,
+ fctx->set_pos_fn, &fctx->iter);
+ if (ret)
+ return ret;
+ }
- obj_request_done_set(obj_request);
+ return __rbd_img_fill_request(img_req);
}
-static void
-rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request)
+/*
+ * Map a list of image extents to a list of object extents, create the
+ * corresponding object requests (normally each to a different object,
+ * but not always) and add them to @img_req. For each object request,
+ * set up its data descriptor to point to the corresponding chunk(s) of
+ * @fctx->pos data buffer.
+ *
+ * Because ceph_file_to_extents() will merge adjacent object extents
+ * together, each object request's data descriptor may point to multiple
+ * different chunks of @fctx->pos data buffer.
+ *
+ * @fctx->pos data buffer is assumed to be large enough.
+ */
+static int rbd_img_fill_request(struct rbd_img_request *img_req,
+ struct ceph_file_extent *img_extents,
+ u32 num_img_extents,
+ struct rbd_img_fill_ctx *fctx)
{
- struct rbd_obj_request *orig_request;
- struct ceph_osd_request *osd_req;
- struct rbd_device *rbd_dev;
- struct page **pages;
- enum obj_operation_type op_type;
- u32 page_count;
- int img_result;
- u64 parent_length;
-
- rbd_assert(img_request_child_test(img_request));
-
- /* First get what we need from the image request */
-
- pages = img_request->copyup_pages;
- rbd_assert(pages != NULL);
- img_request->copyup_pages = NULL;
- page_count = img_request->copyup_page_count;
- rbd_assert(page_count);
- img_request->copyup_page_count = 0;
-
- orig_request = img_request->obj_request;
- rbd_assert(orig_request != NULL);
- rbd_assert(obj_request_type_valid(orig_request->type));
- img_result = img_request->result;
- parent_length = img_request->length;
- rbd_assert(img_result || parent_length == img_request->xferred);
- rbd_img_request_put(img_request);
+ struct rbd_device *rbd_dev = img_req->rbd_dev;
+ struct rbd_obj_request *obj_req;
+ u32 i;
+ int ret;
- rbd_assert(orig_request->img_request);
- rbd_dev = orig_request->img_request->rbd_dev;
- rbd_assert(rbd_dev);
+ if (fctx->pos_type == OBJ_REQUEST_NODATA ||
+ !rbd_layout_is_fancy(&rbd_dev->layout))
+ return rbd_img_fill_request_nocopy(img_req, img_extents,
+ num_img_extents, fctx);
+
+ img_req->data_type = OBJ_REQUEST_OWN_BVECS;
/*
- * If the overlap has become 0 (most likely because the
- * image has been flattened) we need to free the pages
- * and re-submit the original write request.
+ * Create object requests and determine ->bvec_count for each object
+ * request. Note that ->bvec_count sum over all object requests may
+ * be greater than the number of bio_vecs in the provided bio (list)
+ * or bio_vec array because when mapped, those bio_vecs can straddle
+ * stripe unit boundaries.
*/
- if (!rbd_dev->parent_overlap) {
- ceph_release_page_vector(pages, page_count);
- rbd_obj_request_submit(orig_request);
- return;
+ fctx->iter = *fctx->pos;
+ for (i = 0; i < num_img_extents; i++) {
+ ret = ceph_file_to_extents(&rbd_dev->layout,
+ img_extents[i].fe_off,
+ img_extents[i].fe_len,
+ &img_req->object_extents,
+ alloc_object_extent, img_req,
+ fctx->count_fn, &fctx->iter);
+ if (ret)
+ return ret;
}
- if (img_result)
- goto out_err;
+ for_each_obj_request(img_req, obj_req) {
+ obj_req->bvec_pos.bvecs = kmalloc_array(obj_req->bvec_count,
+ sizeof(*obj_req->bvec_pos.bvecs),
+ GFP_NOIO);
+ if (!obj_req->bvec_pos.bvecs)
+ return -ENOMEM;
+ }
/*
- * The original osd request is of no use to use any more.
- * We need a new one that can hold the three ops in a copyup
- * request. Allocate the new copyup osd request for the
- * original request, and release the old one.
+ * Fill in each object request's private bio_vec array, splitting and
+ * rearranging the provided bio_vecs in stripe unit chunks as needed.
*/
- img_result = -ENOMEM;
- osd_req = rbd_osd_req_create_copyup(orig_request);
- if (!osd_req)
- goto out_err;
- rbd_osd_req_destroy(orig_request->osd_req);
- orig_request->osd_req = osd_req;
- orig_request->copyup_pages = pages;
- orig_request->copyup_page_count = page_count;
+ fctx->iter = *fctx->pos;
+ for (i = 0; i < num_img_extents; i++) {
+ ret = ceph_iterate_extents(&rbd_dev->layout,
+ img_extents[i].fe_off,
+ img_extents[i].fe_len,
+ &img_req->object_extents,
+ fctx->copy_fn, &fctx->iter);
+ if (ret)
+ return ret;
+ }
- /* Initialize the copyup op */
+ return __rbd_img_fill_request(img_req);
+}
- osd_req_op_cls_init(osd_req, 0, CEPH_OSD_OP_CALL, "rbd", "copyup");
- osd_req_op_cls_request_data_pages(osd_req, 0, pages, parent_length, 0,
- false, false);
+static int rbd_img_fill_nodata(struct rbd_img_request *img_req,
+ u64 off, u64 len)
+{
+ struct ceph_file_extent ex = { off, len };
+ union rbd_img_fill_iter dummy;
+ struct rbd_img_fill_ctx fctx = {
+ .pos_type = OBJ_REQUEST_NODATA,
+ .pos = &dummy,
+ };
- /* Add the other op(s) */
+ return rbd_img_fill_request(img_req, &ex, 1, &fctx);
+}
- op_type = rbd_img_request_op_type(orig_request->img_request);
- rbd_img_obj_request_fill(orig_request, osd_req, op_type, 1);
+static void set_bio_pos(struct ceph_object_extent *ex, u32 bytes, void *arg)
+{
+ struct rbd_obj_request *obj_req =
+ container_of(ex, struct rbd_obj_request, ex);
+ struct ceph_bio_iter *it = arg;
- /* All set, send it off. */
+ dout("%s objno %llu bytes %u\n", __func__, ex->oe_objno, bytes);
+ obj_req->bio_pos = *it;
+ ceph_bio_iter_advance(it, bytes);
+}
- rbd_obj_request_submit(orig_request);
- return;
+static void count_bio_bvecs(struct ceph_object_extent *ex, u32 bytes, void *arg)
+{
+ struct rbd_obj_request *obj_req =
+ container_of(ex, struct rbd_obj_request, ex);
+ struct ceph_bio_iter *it = arg;
+
+ dout("%s objno %llu bytes %u\n", __func__, ex->oe_objno, bytes);
+ ceph_bio_iter_advance_step(it, bytes, ({
+ obj_req->bvec_count++;
+ }));
-out_err:
- ceph_release_page_vector(pages, page_count);
- rbd_obj_request_error(orig_request, img_result);
}
-/*
- * Read from the parent image the range of data that covers the
- * entire target of the given object request. This is used for
- * satisfying a layered image write request when the target of an
- * object request from the image request does not exist.
- *
- * A page array big enough to hold the returned data is allocated
- * and supplied to rbd_img_request_fill() as the "data descriptor."
- * When the read completes, this page array will be transferred to
- * the original object request for the copyup operation.
- *
- * If an error occurs, it is recorded as the result of the original
- * object request in rbd_img_obj_exists_callback().
- */
-static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request)
-{
- struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev;
- struct rbd_img_request *parent_request = NULL;
- u64 img_offset;
- u64 length;
- struct page **pages = NULL;
- u32 page_count;
- int result;
+static void copy_bio_bvecs(struct ceph_object_extent *ex, u32 bytes, void *arg)
+{
+ struct rbd_obj_request *obj_req =
+ container_of(ex, struct rbd_obj_request, ex);
+ struct ceph_bio_iter *it = arg;
- rbd_assert(rbd_dev->parent != NULL);
+ dout("%s objno %llu bytes %u\n", __func__, ex->oe_objno, bytes);
+ ceph_bio_iter_advance_step(it, bytes, ({
+ obj_req->bvec_pos.bvecs[obj_req->bvec_idx++] = bv;
+ obj_req->bvec_pos.iter.bi_size += bv.bv_len;
+ }));
+}
- /*
- * Determine the byte range covered by the object in the
- * child image to which the original request was to be sent.
- */
- img_offset = obj_request->img_offset - obj_request->offset;
- length = rbd_obj_bytes(&rbd_dev->header);
+static int __rbd_img_fill_from_bio(struct rbd_img_request *img_req,
+ struct ceph_file_extent *img_extents,
+ u32 num_img_extents,
+ struct ceph_bio_iter *bio_pos)
+{
+ struct rbd_img_fill_ctx fctx = {
+ .pos_type = OBJ_REQUEST_BIO,
+ .pos = (union rbd_img_fill_iter *)bio_pos,
+ .set_pos_fn = set_bio_pos,
+ .count_fn = count_bio_bvecs,
+ .copy_fn = copy_bio_bvecs,
+ };
- /*
- * There is no defined parent data beyond the parent
- * overlap, so limit what we read at that boundary if
- * necessary.
- */
- if (img_offset + length > rbd_dev->parent_overlap) {
- rbd_assert(img_offset < rbd_dev->parent_overlap);
- length = rbd_dev->parent_overlap - img_offset;
- }
+ return rbd_img_fill_request(img_req, img_extents, num_img_extents,
+ &fctx);
+}
- /*
- * Allocate a page array big enough to receive the data read
- * from the parent.
- */
- page_count = (u32)calc_pages_for(0, length);
- pages = ceph_alloc_page_vector(page_count, GFP_NOIO);
- if (IS_ERR(pages)) {
- result = PTR_ERR(pages);
- pages = NULL;
- goto out_err;
- }
+static int rbd_img_fill_from_bio(struct rbd_img_request *img_req,
+ u64 off, u64 len, struct bio *bio)
+{
+ struct ceph_file_extent ex = { off, len };
+ struct ceph_bio_iter it = { .bio = bio, .iter = bio->bi_iter };
- result = -ENOMEM;
- parent_request = rbd_parent_request_create(obj_request,
- img_offset, length);
- if (!parent_request)
- goto out_err;
+ return __rbd_img_fill_from_bio(img_req, &ex, 1, &it);
+}
- result = rbd_img_request_fill(parent_request, OBJ_REQUEST_PAGES, pages);
- if (result)
- goto out_err;
+static void set_bvec_pos(struct ceph_object_extent *ex, u32 bytes, void *arg)
+{
+ struct rbd_obj_request *obj_req =
+ container_of(ex, struct rbd_obj_request, ex);
+ struct ceph_bvec_iter *it = arg;
- parent_request->copyup_pages = pages;
- parent_request->copyup_page_count = page_count;
- parent_request->callback = rbd_img_obj_parent_read_full_callback;
+ obj_req->bvec_pos = *it;
+ ceph_bvec_iter_shorten(&obj_req->bvec_pos, bytes);
+ ceph_bvec_iter_advance(it, bytes);
+}
- result = rbd_img_request_submit(parent_request);
- if (!result)
- return 0;
+static void count_bvecs(struct ceph_object_extent *ex, u32 bytes, void *arg)
+{
+ struct rbd_obj_request *obj_req =
+ container_of(ex, struct rbd_obj_request, ex);
+ struct ceph_bvec_iter *it = arg;
- parent_request->copyup_pages = NULL;
- parent_request->copyup_page_count = 0;
-out_err:
- if (pages)
- ceph_release_page_vector(pages, page_count);
- if (parent_request)
- rbd_img_request_put(parent_request);
- return result;
+ ceph_bvec_iter_advance_step(it, bytes, ({
+ obj_req->bvec_count++;
+ }));
}
-static void rbd_img_obj_exists_callback(struct rbd_obj_request *obj_request)
+static void copy_bvecs(struct ceph_object_extent *ex, u32 bytes, void *arg)
{
- struct rbd_obj_request *orig_request;
- struct rbd_device *rbd_dev;
- int result;
+ struct rbd_obj_request *obj_req =
+ container_of(ex, struct rbd_obj_request, ex);
+ struct ceph_bvec_iter *it = arg;
- rbd_assert(!obj_request_img_data_test(obj_request));
+ ceph_bvec_iter_advance_step(it, bytes, ({
+ obj_req->bvec_pos.bvecs[obj_req->bvec_idx++] = bv;
+ obj_req->bvec_pos.iter.bi_size += bv.bv_len;
+ }));
+}
- /*
- * All we need from the object request is the original
- * request and the result of the STAT op. Grab those, then
- * we're done with the request.
- */
- orig_request = obj_request->obj_request;
- obj_request->obj_request = NULL;
- rbd_obj_request_put(orig_request);
- rbd_assert(orig_request);
- rbd_assert(orig_request->img_request);
-
- result = obj_request->result;
- obj_request->result = 0;
-
- dout("%s: obj %p for obj %p result %d %llu/%llu\n", __func__,
- obj_request, orig_request, result,
- obj_request->xferred, obj_request->length);
- rbd_obj_request_put(obj_request);
+static int __rbd_img_fill_from_bvecs(struct rbd_img_request *img_req,
+ struct ceph_file_extent *img_extents,
+ u32 num_img_extents,
+ struct ceph_bvec_iter *bvec_pos)
+{
+ struct rbd_img_fill_ctx fctx = {
+ .pos_type = OBJ_REQUEST_BVECS,
+ .pos = (union rbd_img_fill_iter *)bvec_pos,
+ .set_pos_fn = set_bvec_pos,
+ .count_fn = count_bvecs,
+ .copy_fn = copy_bvecs,
+ };
- /*
- * If the overlap has become 0 (most likely because the
- * image has been flattened) we need to re-submit the
- * original request.
- */
- rbd_dev = orig_request->img_request->rbd_dev;
- if (!rbd_dev->parent_overlap) {
- rbd_obj_request_submit(orig_request);
- return;
- }
+ return rbd_img_fill_request(img_req, img_extents, num_img_extents,
+ &fctx);
+}
- /*
- * Our only purpose here is to determine whether the object
- * exists, and we don't want to treat the non-existence as
- * an error. If something else comes back, transfer the
- * error to the original request and complete it now.
- */
- if (!result) {
- obj_request_existence_set(orig_request, true);
- } else if (result == -ENOENT) {
- obj_request_existence_set(orig_request, false);
- } else {
- goto fail_orig_request;
- }
+static int rbd_img_fill_from_bvecs(struct rbd_img_request *img_req,
+ struct ceph_file_extent *img_extents,
+ u32 num_img_extents,
+ struct bio_vec *bvecs)
+{
+ struct ceph_bvec_iter it = {
+ .bvecs = bvecs,
+ .iter = { .bi_size = ceph_file_extents_bytes(img_extents,
+ num_img_extents) },
+ };
- /*
- * Resubmit the original request now that we have recorded
- * whether the target object exists.
- */
- result = rbd_img_obj_request_submit(orig_request);
- if (result)
- goto fail_orig_request;
+ return __rbd_img_fill_from_bvecs(img_req, img_extents, num_img_extents,
+ &it);
+}
- return;
+static void rbd_img_request_submit(struct rbd_img_request *img_request)
+{
+ struct rbd_obj_request *obj_request;
+
+ dout("%s: img %p\n", __func__, img_request);
+
+ rbd_img_request_get(img_request);
+ for_each_obj_request(img_request, obj_request)
+ rbd_obj_request_submit(obj_request);
-fail_orig_request:
- rbd_obj_request_error(orig_request, result);
+ rbd_img_request_put(img_request);
}
-static int rbd_img_obj_exists_submit(struct rbd_obj_request *obj_request)
+static int rbd_obj_read_from_parent(struct rbd_obj_request *obj_req)
{
- struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev;
- struct rbd_obj_request *stat_request;
- struct page **pages;
- u32 page_count;
- size_t size;
+ struct rbd_img_request *img_req = obj_req->img_request;
+ struct rbd_img_request *child_img_req;
int ret;
- stat_request = rbd_obj_request_create(OBJ_REQUEST_PAGES);
- if (!stat_request)
+ child_img_req = rbd_img_request_create(img_req->rbd_dev->parent,
+ OBJ_OP_READ, NULL);
+ if (!child_img_req)
return -ENOMEM;
- stat_request->object_no = obj_request->object_no;
+ __set_bit(IMG_REQ_CHILD, &child_img_req->flags);
+ child_img_req->obj_request = obj_req;
- stat_request->osd_req = rbd_osd_req_create(rbd_dev, OBJ_OP_READ, 1,
- stat_request);
- if (!stat_request->osd_req) {
- ret = -ENOMEM;
- goto fail_stat_request;
+ if (!rbd_img_is_write(img_req)) {
+ switch (img_req->data_type) {
+ case OBJ_REQUEST_BIO:
+ ret = __rbd_img_fill_from_bio(child_img_req,
+ obj_req->img_extents,
+ obj_req->num_img_extents,
+ &obj_req->bio_pos);
+ break;
+ case OBJ_REQUEST_BVECS:
+ case OBJ_REQUEST_OWN_BVECS:
+ ret = __rbd_img_fill_from_bvecs(child_img_req,
+ obj_req->img_extents,
+ obj_req->num_img_extents,
+ &obj_req->bvec_pos);
+ break;
+ default:
+ rbd_assert(0);
+ }
+ } else {
+ ret = rbd_img_fill_from_bvecs(child_img_req,
+ obj_req->img_extents,
+ obj_req->num_img_extents,
+ obj_req->copyup_bvecs);
+ }
+ if (ret) {
+ rbd_img_request_put(child_img_req);
+ return ret;
+ }
+
+ rbd_img_request_submit(child_img_req);
+ return 0;
+}
+
+static bool rbd_obj_handle_read(struct rbd_obj_request *obj_req)
+{
+ struct rbd_device *rbd_dev = obj_req->img_request->rbd_dev;
+ int ret;
+
+ if (obj_req->result == -ENOENT &&
+ rbd_dev->parent_overlap && !obj_req->tried_parent) {
+ /* reverse map this object extent onto the parent */
+ ret = rbd_obj_calc_img_extents(obj_req, false);
+ if (ret) {
+ obj_req->result = ret;
+ return true;
+ }
+
+ if (obj_req->num_img_extents) {
+ obj_req->tried_parent = true;
+ ret = rbd_obj_read_from_parent(obj_req);
+ if (ret) {
+ obj_req->result = ret;
+ return true;
+ }
+ return false;
+ }
}
/*
- * The response data for a STAT call consists of:
- * le64 length;
- * struct {
- * le32 tv_sec;
- * le32 tv_nsec;
- * } mtime;
+ * -ENOENT means a hole in the image -- zero-fill the entire
+ * length of the request. A short read also implies zero-fill
+ * to the end of the request. In both cases we update xferred
+ * count to indicate the whole request was satisfied.
*/
- size = sizeof (__le64) + sizeof (__le32) + sizeof (__le32);
- page_count = (u32)calc_pages_for(0, size);
- pages = ceph_alloc_page_vector(page_count, GFP_NOIO);
- if (IS_ERR(pages)) {
- ret = PTR_ERR(pages);
- goto fail_stat_request;
+ if (obj_req->result == -ENOENT ||
+ (!obj_req->result && obj_req->xferred < obj_req->ex.oe_len)) {
+ rbd_assert(!obj_req->xferred || !obj_req->result);
+ rbd_obj_zero_range(obj_req, obj_req->xferred,
+ obj_req->ex.oe_len - obj_req->xferred);
+ obj_req->result = 0;
+ obj_req->xferred = obj_req->ex.oe_len;
}
- osd_req_op_init(stat_request->osd_req, 0, CEPH_OSD_OP_STAT, 0);
- osd_req_op_raw_data_in_pages(stat_request->osd_req, 0, pages, size, 0,
- false, false);
-
- rbd_obj_request_get(obj_request);
- stat_request->obj_request = obj_request;
- stat_request->pages = pages;
- stat_request->page_count = page_count;
- stat_request->callback = rbd_img_obj_exists_callback;
+ return true;
+}
- rbd_obj_request_submit(stat_request);
- return 0;
+/*
+ * copyup_bvecs pages are never highmem pages
+ */
+static bool is_zero_bvecs(struct bio_vec *bvecs, u32 bytes)
+{
+ struct ceph_bvec_iter it = {
+ .bvecs = bvecs,
+ .iter = { .bi_size = bytes },
+ };
-fail_stat_request:
- rbd_obj_request_put(stat_request);
- return ret;
+ ceph_bvec_iter_advance_step(&it, bytes, ({
+ if (memchr_inv(page_address(bv.bv_page) + bv.bv_offset, 0,
+ bv.bv_len))
+ return false;
+ }));
+ return true;
}
-static bool img_obj_request_simple(struct rbd_obj_request *obj_request)
+static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
{
- struct rbd_img_request *img_request = obj_request->img_request;
- struct rbd_device *rbd_dev = img_request->rbd_dev;
+ unsigned int num_osd_ops = obj_req->osd_req->r_num_ops;
- /* Reads */
- if (!img_request_write_test(img_request) &&
- !img_request_discard_test(img_request))
- return true;
-
- /* Non-layered writes */
- if (!img_request_layered_test(img_request))
- return true;
+ dout("%s obj_req %p bytes %u\n", __func__, obj_req, bytes);
+ rbd_assert(obj_req->osd_req->r_ops[0].op == CEPH_OSD_OP_STAT);
+ rbd_osd_req_destroy(obj_req->osd_req);
/*
- * Layered writes outside of the parent overlap range don't
- * share any data with the parent.
+ * Create a copyup request with the same number of OSD ops as
+ * the original request. The original request was stat + op(s),
+ * the new copyup request will be copyup + the same op(s).
*/
- if (!obj_request_overlaps_parent(obj_request))
- return true;
+ obj_req->osd_req = rbd_osd_req_create(obj_req, num_osd_ops);
+ if (!obj_req->osd_req)
+ return -ENOMEM;
/*
- * Entire-object layered writes - we will overwrite whatever
- * parent data there is anyway.
+ * Only send non-zero copyup data to save some I/O and network
+ * bandwidth -- zero copyup data is equivalent to the object not
+ * existing.
*/
- if (!obj_request->offset &&
- obj_request->length == rbd_obj_bytes(&rbd_dev->header))
- return true;
+ if (is_zero_bvecs(obj_req->copyup_bvecs, bytes)) {
+ dout("%s obj_req %p detected zeroes\n", __func__, obj_req);
+ bytes = 0;
+ }
- /*
- * If the object is known to already exist, its parent data has
- * already been copied.
- */
- if (obj_request_known_test(obj_request) &&
- obj_request_exists_test(obj_request))
- return true;
+ osd_req_op_cls_init(obj_req->osd_req, 0, CEPH_OSD_OP_CALL, "rbd",
+ "copyup");
+ osd_req_op_cls_request_data_bvecs(obj_req->osd_req, 0,
+ obj_req->copyup_bvecs, bytes);
+
+ switch (obj_req->img_request->op_type) {
+ case OBJ_OP_WRITE:
+ __rbd_obj_setup_write(obj_req, 1);
+ break;
+ case OBJ_OP_DISCARD:
+ rbd_assert(!rbd_obj_is_entire(obj_req));
+ __rbd_obj_setup_discard(obj_req, 1);
+ break;
+ default:
+ rbd_assert(0);
+ }
- return false;
+ rbd_obj_request_submit(obj_req);
+ return 0;
}
-static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request)
+static int setup_copyup_bvecs(struct rbd_obj_request *obj_req, u64 obj_overlap)
{
- rbd_assert(obj_request_img_data_test(obj_request));
- rbd_assert(obj_request_type_valid(obj_request->type));
- rbd_assert(obj_request->img_request);
+ u32 i;
- if (img_obj_request_simple(obj_request)) {
- rbd_obj_request_submit(obj_request);
- return 0;
- }
+ rbd_assert(!obj_req->copyup_bvecs);
+ obj_req->copyup_bvec_count = calc_pages_for(0, obj_overlap);
+ obj_req->copyup_bvecs = kcalloc(obj_req->copyup_bvec_count,
+ sizeof(*obj_req->copyup_bvecs),
+ GFP_NOIO);
+ if (!obj_req->copyup_bvecs)
+ return -ENOMEM;
- /*
- * It's a layered write. The target object might exist but
- * we may not know that yet. If we know it doesn't exist,
- * start by reading the data for the full target object from
- * the parent so we can use it for a copyup to the target.
- */
- if (obj_request_known_test(obj_request))
- return rbd_img_obj_parent_read_full(obj_request);
+ for (i = 0; i < obj_req->copyup_bvec_count; i++) {
+ unsigned int len = min(obj_overlap, (u64)PAGE_SIZE);
- /* We don't know whether the target exists. Go find out. */
+ obj_req->copyup_bvecs[i].bv_page = alloc_page(GFP_NOIO);
+ if (!obj_req->copyup_bvecs[i].bv_page)
+ return -ENOMEM;
+
+ obj_req->copyup_bvecs[i].bv_offset = 0;
+ obj_req->copyup_bvecs[i].bv_len = len;
+ obj_overlap -= len;
+ }
- return rbd_img_obj_exists_submit(obj_request);
+ rbd_assert(!obj_overlap);
+ return 0;
}
-static int rbd_img_request_submit(struct rbd_img_request *img_request)
+static int rbd_obj_handle_write_guard(struct rbd_obj_request *obj_req)
{
- struct rbd_obj_request *obj_request;
- struct rbd_obj_request *next_obj_request;
- int ret = 0;
-
- dout("%s: img %p\n", __func__, img_request);
+ struct rbd_device *rbd_dev = obj_req->img_request->rbd_dev;
+ int ret;
- rbd_img_request_get(img_request);
- for_each_obj_request_safe(img_request, obj_request, next_obj_request) {
- ret = rbd_img_obj_request_submit(obj_request);
- if (ret)
- goto out_put_ireq;
+ rbd_assert(obj_req->num_img_extents);
+ prune_extents(obj_req->img_extents, &obj_req->num_img_extents,
+ rbd_dev->parent_overlap);
+ if (!obj_req->num_img_extents) {
+ /*
+ * The overlap has become 0 (most likely because the
+ * image has been flattened). Use rbd_obj_issue_copyup()
+ * to re-submit the original write request -- the copyup
+ * operation itself will be a no-op, since someone must
+ * have populated the child object while we weren't
+ * looking. Move to WRITE_FLAT state as we'll be done
+ * with the operation once the null copyup completes.
+ */
+ obj_req->write_state = RBD_OBJ_WRITE_FLAT;
+ return rbd_obj_issue_copyup(obj_req, 0);
}
-out_put_ireq:
- rbd_img_request_put(img_request);
- return ret;
+ ret = setup_copyup_bvecs(obj_req, rbd_obj_img_extents_bytes(obj_req));
+ if (ret)
+ return ret;
+
+ obj_req->write_state = RBD_OBJ_WRITE_COPYUP;
+ return rbd_obj_read_from_parent(obj_req);
}
-static void rbd_img_parent_read_callback(struct rbd_img_request *img_request)
+static bool rbd_obj_handle_write(struct rbd_obj_request *obj_req)
{
- struct rbd_obj_request *obj_request;
- struct rbd_device *rbd_dev;
- u64 obj_end;
- u64 img_xferred;
- int img_result;
+ int ret;
- rbd_assert(img_request_child_test(img_request));
+again:
+ switch (obj_req->write_state) {
+ case RBD_OBJ_WRITE_GUARD:
+ rbd_assert(!obj_req->xferred);
+ if (obj_req->result == -ENOENT) {
+ /*
+ * The target object doesn't exist. Read the data for
+ * the entire target object up to the overlap point (if
+ * any) from the parent, so we can use it for a copyup.
+ */
+ ret = rbd_obj_handle_write_guard(obj_req);
+ if (ret) {
+ obj_req->result = ret;
+ return true;
+ }
+ return false;
+ }
+ /* fall through */
+ case RBD_OBJ_WRITE_FLAT:
+ if (!obj_req->result)
+ /*
+ * There is no such thing as a successful short
+ * write -- indicate the whole request was satisfied.
+ */
+ obj_req->xferred = obj_req->ex.oe_len;
+ return true;
+ case RBD_OBJ_WRITE_COPYUP:
+ obj_req->write_state = RBD_OBJ_WRITE_GUARD;
+ if (obj_req->result)
+ goto again;
- /* First get what we need from the image request and release it */
+ rbd_assert(obj_req->xferred);
+ ret = rbd_obj_issue_copyup(obj_req, obj_req->xferred);
+ if (ret) {
+ obj_req->result = ret;
+ return true;
+ }
+ return false;
+ default:
+ rbd_assert(0);
+ }
+}
- obj_request = img_request->obj_request;
- img_xferred = img_request->xferred;
- img_result = img_request->result;
- rbd_img_request_put(img_request);
+/*
+ * Returns true if @obj_req is completed, or false otherwise.
+ */
+static bool __rbd_obj_handle_request(struct rbd_obj_request *obj_req)
+{
+ switch (obj_req->img_request->op_type) {
+ case OBJ_OP_READ:
+ return rbd_obj_handle_read(obj_req);
+ case OBJ_OP_WRITE:
+ return rbd_obj_handle_write(obj_req);
+ case OBJ_OP_DISCARD:
+ if (rbd_obj_handle_write(obj_req)) {
+ /*
+ * Hide -ENOENT from delete/truncate/zero -- discarding
+ * a non-existent object is not a problem.
+ */
+ if (obj_req->result == -ENOENT) {
+ obj_req->result = 0;
+ obj_req->xferred = obj_req->ex.oe_len;
+ }
+ return true;
+ }
+ return false;
+ default:
+ rbd_assert(0);
+ }
+}
- /*
- * If the overlap has become 0 (most likely because the
- * image has been flattened) we need to re-submit the
- * original request.
- */
- rbd_assert(obj_request);
- rbd_assert(obj_request->img_request);
- rbd_dev = obj_request->img_request->rbd_dev;
- if (!rbd_dev->parent_overlap) {
- rbd_obj_request_submit(obj_request);
+static void rbd_obj_end_request(struct rbd_obj_request *obj_req)
+{
+ struct rbd_img_request *img_req = obj_req->img_request;
+
+ rbd_assert((!obj_req->result &&
+ obj_req->xferred == obj_req->ex.oe_len) ||
+ (obj_req->result < 0 && !obj_req->xferred));
+ if (!obj_req->result) {
+ img_req->xferred += obj_req->xferred;
return;
}
- obj_request->result = img_result;
- if (obj_request->result)
- goto out;
+ rbd_warn(img_req->rbd_dev,
+ "%s at objno %llu %llu~%llu result %d xferred %llu",
+ obj_op_name(img_req->op_type), obj_req->ex.oe_objno,
+ obj_req->ex.oe_off, obj_req->ex.oe_len, obj_req->result,
+ obj_req->xferred);
+ if (!img_req->result) {
+ img_req->result = obj_req->result;
+ img_req->xferred = 0;
+ }
+}
- /*
- * We need to zero anything beyond the parent overlap
- * boundary. Since rbd_img_obj_request_read_callback()
- * will zero anything beyond the end of a short read, an
- * easy way to do this is to pretend the data from the
- * parent came up short--ending at the overlap boundary.
- */
- rbd_assert(obj_request->img_offset < U64_MAX - obj_request->length);
- obj_end = obj_request->img_offset + obj_request->length;
- if (obj_end > rbd_dev->parent_overlap) {
- u64 xferred = 0;
+static void rbd_img_end_child_request(struct rbd_img_request *img_req)
+{
+ struct rbd_obj_request *obj_req = img_req->obj_request;
- if (obj_request->img_offset < rbd_dev->parent_overlap)
- xferred = rbd_dev->parent_overlap -
- obj_request->img_offset;
+ rbd_assert(test_bit(IMG_REQ_CHILD, &img_req->flags));
+ rbd_assert((!img_req->result &&
+ img_req->xferred == rbd_obj_img_extents_bytes(obj_req)) ||
+ (img_req->result < 0 && !img_req->xferred));
- obj_request->xferred = min(img_xferred, xferred);
- } else {
- obj_request->xferred = img_xferred;
- }
-out:
- rbd_img_obj_request_read_callback(obj_request);
- rbd_obj_request_complete(obj_request);
+ obj_req->result = img_req->result;
+ obj_req->xferred = img_req->xferred;
+ rbd_img_request_put(img_req);
}
-static void rbd_img_parent_read(struct rbd_obj_request *obj_request)
+static void rbd_img_end_request(struct rbd_img_request *img_req)
{
- struct rbd_img_request *img_request;
- int result;
+ rbd_assert(!test_bit(IMG_REQ_CHILD, &img_req->flags));
+ rbd_assert((!img_req->result &&
+ img_req->xferred == blk_rq_bytes(img_req->rq)) ||
+ (img_req->result < 0 && !img_req->xferred));
- rbd_assert(obj_request_img_data_test(obj_request));
- rbd_assert(obj_request->img_request != NULL);
- rbd_assert(obj_request->result == (s32) -ENOENT);
- rbd_assert(obj_request_type_valid(obj_request->type));
+ blk_mq_end_request(img_req->rq,
+ errno_to_blk_status(img_req->result));
+ rbd_img_request_put(img_req);
+}
- /* rbd_read_finish(obj_request, obj_request->length); */
- img_request = rbd_parent_request_create(obj_request,
- obj_request->img_offset,
- obj_request->length);
- result = -ENOMEM;
- if (!img_request)
- goto out_err;
+static void rbd_obj_handle_request(struct rbd_obj_request *obj_req)
+{
+ struct rbd_img_request *img_req;
- if (obj_request->type == OBJ_REQUEST_BIO)
- result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO,
- obj_request->bio_list);
- else
- result = rbd_img_request_fill(img_request, OBJ_REQUEST_PAGES,
- obj_request->pages);
- if (result)
- goto out_err;
+again:
+ if (!__rbd_obj_handle_request(obj_req))
+ return;
- img_request->callback = rbd_img_parent_read_callback;
- result = rbd_img_request_submit(img_request);
- if (result)
- goto out_err;
+ img_req = obj_req->img_request;
+ spin_lock(&img_req->completion_lock);
+ rbd_obj_end_request(obj_req);
+ rbd_assert(img_req->pending_count);
+ if (--img_req->pending_count) {
+ spin_unlock(&img_req->completion_lock);
+ return;
+ }
- return;
-out_err:
- if (img_request)
- rbd_img_request_put(img_request);
- obj_request->result = result;
- obj_request->xferred = 0;
- obj_request_done_set(obj_request);
+ spin_unlock(&img_req->completion_lock);
+ if (test_bit(IMG_REQ_CHILD, &img_req->flags)) {
+ obj_req = img_req->obj_request;
+ rbd_img_end_child_request(img_req);
+ goto again;
+ }
+ rbd_img_end_request(img_req);
}
static const struct rbd_client_id rbd_empty_cid;
@@ -3091,8 +2674,8 @@ static int __rbd_notify_op_lock(struct rbd_device *rbd_dev,
{
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
struct rbd_client_id cid = rbd_get_cid(rbd_dev);
- int buf_size = 4 + 8 + 8 + CEPH_ENCODING_START_BLK_LEN;
- char buf[buf_size];
+ char buf[4 + 8 + 8 + CEPH_ENCODING_START_BLK_LEN];
+ int buf_size = sizeof(buf);
void *p = buf;
dout("%s rbd_dev %p notify_op %d\n", __func__, rbd_dev, notify_op);
@@ -3610,8 +3193,8 @@ static void __rbd_acknowledge_notify(struct rbd_device *rbd_dev,
u64 notify_id, u64 cookie, s32 *result)
{
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
- int buf_size = 4 + CEPH_ENCODING_START_BLK_LEN;
- char buf[buf_size];
+ char buf[4 + CEPH_ENCODING_START_BLK_LEN];
+ int buf_size = sizeof(buf);
int ret;
if (result) {
@@ -3887,7 +3470,7 @@ static void rbd_reregister_watch(struct work_struct *work)
ret = rbd_dev_refresh(rbd_dev);
if (ret)
- rbd_warn(rbd_dev, "reregisteration refresh failed: %d", ret);
+ rbd_warn(rbd_dev, "reregistration refresh failed: %d", ret);
}
/*
@@ -4070,8 +3653,7 @@ static void rbd_queue_workfn(struct work_struct *work)
}
}
- img_request = rbd_img_request_create(rbd_dev, offset, length, op_type,
- snapc);
+ img_request = rbd_img_request_create(rbd_dev, op_type, snapc);
if (!img_request) {
result = -ENOMEM;
goto err_unlock;
@@ -4080,18 +3662,14 @@ static void rbd_queue_workfn(struct work_struct *work)
snapc = NULL; /* img_request consumes a ref */
if (op_type == OBJ_OP_DISCARD)
- result = rbd_img_request_fill(img_request, OBJ_REQUEST_NODATA,
- NULL);
+ result = rbd_img_fill_nodata(img_request, offset, length);
else
- result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO,
- rq->bio);
- if (result)
- goto err_img_request;
-
- result = rbd_img_request_submit(img_request);
+ result = rbd_img_fill_from_bio(img_request, offset, length,
+ rq->bio);
if (result)
goto err_img_request;
+ rbd_img_request_submit(img_request);
if (must_be_locked)
up_read(&rbd_dev->lock_rwsem);
return;
@@ -4369,7 +3947,7 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
blk_queue_max_hw_sectors(q, segment_size / SECTOR_SIZE);
q->limits.max_sectors = queue_max_hw_sectors(q);
blk_queue_max_segments(q, USHRT_MAX);
- blk_queue_max_segment_size(q, segment_size);
+ blk_queue_max_segment_size(q, UINT_MAX);
blk_queue_io_min(q, segment_size);
blk_queue_io_opt(q, segment_size);
@@ -5057,9 +4635,6 @@ static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev)
} __attribute__ ((packed)) striping_info_buf = { 0 };
size_t size = sizeof (striping_info_buf);
void *p;
- u64 obj_size;
- u64 stripe_unit;
- u64 stripe_count;
int ret;
ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid,
@@ -5071,31 +4646,9 @@ static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev)
if (ret < size)
return -ERANGE;
- /*
- * We don't actually support the "fancy striping" feature
- * (STRIPINGV2) yet, but if the striping sizes are the
- * defaults the behavior is the same as before. So find
- * out, and only fail if the image has non-default values.
- */
- ret = -EINVAL;
- obj_size = rbd_obj_bytes(&rbd_dev->header);
p = &striping_info_buf;
- stripe_unit = ceph_decode_64(&p);
- if (stripe_unit != obj_size) {
- rbd_warn(rbd_dev, "unsupported stripe unit "
- "(got %llu want %llu)",
- stripe_unit, obj_size);
- return -EINVAL;
- }
- stripe_count = ceph_decode_64(&p);
- if (stripe_count != 1) {
- rbd_warn(rbd_dev, "unsupported stripe count "
- "(got %llu want 1)", stripe_count);
- return -EINVAL;
- }
- rbd_dev->header.stripe_unit = stripe_unit;
- rbd_dev->header.stripe_count = stripe_count;
-
+ rbd_dev->header.stripe_unit = ceph_decode_64(&p);
+ rbd_dev->header.stripe_count = ceph_decode_64(&p);
return 0;
}
@@ -5653,39 +5206,6 @@ out_err:
return ret;
}
-/*
- * Return pool id (>= 0) or a negative error code.
- */
-static int rbd_add_get_pool_id(struct rbd_client *rbdc, const char *pool_name)
-{
- struct ceph_options *opts = rbdc->client->options;
- u64 newest_epoch;
- int tries = 0;
- int ret;
-
-again:
- ret = ceph_pg_poolid_by_name(rbdc->client->osdc.osdmap, pool_name);
- if (ret == -ENOENT && tries++ < 1) {
- ret = ceph_monc_get_version(&rbdc->client->monc, "osdmap",
- &newest_epoch);
- if (ret < 0)
- return ret;
-
- if (rbdc->client->osdc.osdmap->epoch < newest_epoch) {
- ceph_osdc_maybe_request_map(&rbdc->client->osdc);
- (void) ceph_monc_wait_osdmap(&rbdc->client->monc,
- newest_epoch,
- opts->mount_timeout);
- goto again;
- } else {
- /* the osdmap we have is new enough */
- return -ENOENT;
- }
- }
-
- return ret;
-}
-
static void rbd_dev_image_unlock(struct rbd_device *rbd_dev)
{
down_write(&rbd_dev->lock_rwsem);
@@ -6114,7 +5634,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
}
/* pick the pool */
- rc = rbd_add_get_pool_id(rbdc, spec->pool_name);
+ rc = ceph_pg_poolid_by_name(rbdc->client->osdc.osdmap, spec->pool_name);
if (rc < 0) {
if (rc == -ENOENT)
pr_info("pool %s does not exist\n", spec->pool_name);
@@ -6366,16 +5886,8 @@ static int rbd_slab_init(void)
if (!rbd_obj_request_cache)
goto out_err;
- rbd_assert(!rbd_bio_clone);
- rbd_bio_clone = bioset_create(BIO_POOL_SIZE, 0, 0);
- if (!rbd_bio_clone)
- goto out_err_clone;
-
return 0;
-out_err_clone:
- kmem_cache_destroy(rbd_obj_request_cache);
- rbd_obj_request_cache = NULL;
out_err:
kmem_cache_destroy(rbd_img_request_cache);
rbd_img_request_cache = NULL;
@@ -6391,10 +5903,6 @@ static void rbd_slab_exit(void)
rbd_assert(rbd_img_request_cache);
kmem_cache_destroy(rbd_img_request_cache);
rbd_img_request_cache = NULL;
-
- rbd_assert(rbd_bio_clone);
- bioset_free(rbd_bio_clone);
- rbd_bio_clone = NULL;
}
static int __init rbd_init(void)
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 0c858d027bf3..57dc546628b5 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -809,89 +809,6 @@ static __poll_t rtc_poll(struct file *file, poll_table *wait)
}
#endif
-int rtc_register(rtc_task_t *task)
-{
-#ifndef RTC_IRQ
- return -EIO;
-#else
- if (task == NULL || task->func == NULL)
- return -EINVAL;
- spin_lock_irq(&rtc_lock);
- if (rtc_status & RTC_IS_OPEN) {
- spin_unlock_irq(&rtc_lock);
- return -EBUSY;
- }
- spin_lock(&rtc_task_lock);
- if (rtc_callback) {
- spin_unlock(&rtc_task_lock);
- spin_unlock_irq(&rtc_lock);
- return -EBUSY;
- }
- rtc_status |= RTC_IS_OPEN;
- rtc_callback = task;
- spin_unlock(&rtc_task_lock);
- spin_unlock_irq(&rtc_lock);
- return 0;
-#endif
-}
-EXPORT_SYMBOL(rtc_register);
-
-int rtc_unregister(rtc_task_t *task)
-{
-#ifndef RTC_IRQ
- return -EIO;
-#else
- unsigned char tmp;
-
- spin_lock_irq(&rtc_lock);
- spin_lock(&rtc_task_lock);
- if (rtc_callback != task) {
- spin_unlock(&rtc_task_lock);
- spin_unlock_irq(&rtc_lock);
- return -ENXIO;
- }
- rtc_callback = NULL;
-
- /* disable controls */
- if (!hpet_mask_rtc_irq_bit(RTC_PIE | RTC_AIE | RTC_UIE)) {
- tmp = CMOS_READ(RTC_CONTROL);
- tmp &= ~RTC_PIE;
- tmp &= ~RTC_AIE;
- tmp &= ~RTC_UIE;
- CMOS_WRITE(tmp, RTC_CONTROL);
- CMOS_READ(RTC_INTR_FLAGS);
- }
- if (rtc_status & RTC_TIMER_ON) {
- rtc_status &= ~RTC_TIMER_ON;
- del_timer(&rtc_irq_timer);
- }
- rtc_status &= ~RTC_IS_OPEN;
- spin_unlock(&rtc_task_lock);
- spin_unlock_irq(&rtc_lock);
- return 0;
-#endif
-}
-EXPORT_SYMBOL(rtc_unregister);
-
-int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
-{
-#ifndef RTC_IRQ
- return -EIO;
-#else
- unsigned long flags;
- if (cmd != RTC_PIE_ON && cmd != RTC_PIE_OFF && cmd != RTC_IRQP_SET)
- return -EINVAL;
- spin_lock_irqsave(&rtc_task_lock, flags);
- if (rtc_callback != task) {
- spin_unlock_irqrestore(&rtc_task_lock, flags);
- return -ENXIO;
- }
- spin_unlock_irqrestore(&rtc_task_lock, flags);
- return rtc_do_ioctl(cmd, arg, 1);
-#endif
-}
-EXPORT_SYMBOL(rtc_control);
-
/*
* The various file operations we support.
*/
diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
index c6ebc88a7d8d..72a2975499db 100644
--- a/drivers/cpufreq/armada-37xx-cpufreq.c
+++ b/drivers/cpufreq/armada-37xx-cpufreq.c
@@ -202,6 +202,7 @@ static int __init armada37xx_cpufreq_driver_init(void)
cur_frequency = clk_get_rate(clk);
if (!cur_frequency) {
dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
+ clk_put(clk);
return -EINVAL;
}
@@ -210,6 +211,7 @@ static int __init armada37xx_cpufreq_driver_init(void)
return -EINVAL;
armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
+ clk_put(clk);
for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
load_lvl++) {
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 8300a9fcb80c..bc5fc1630876 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -162,14 +162,23 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpu->perf_caps.highest_perf;
policy->cpuinfo.max_freq = cppc_dmi_max_khz;
- policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num);
policy->transition_delay_us = cppc_get_transition_latency(cpu_num) /
NSEC_PER_USEC;
policy->shared_type = cpu->shared_type;
- if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+ if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
+ int i;
+
cpumask_copy(policy->cpus, cpu->shared_cpu_map);
- else if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL) {
+
+ for_each_cpu(i, policy->cpus) {
+ if (unlikely(i == policy->cpu))
+ continue;
+
+ memcpy(&all_cpu_data[i]->perf_caps, &cpu->perf_caps,
+ sizeof(cpu->perf_caps));
+ }
+ } else if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL) {
/* Support only SW_ANY for now. */
pr_debug("Unsupported CPU co-ord type\n");
return -EFAULT;
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 10e119ae66dd..3a8cc99e6815 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -352,20 +352,6 @@ static int set_freq_table_sorted(struct cpufreq_policy *policy)
return 0;
}
-int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
- struct cpufreq_frequency_table *table)
-{
- int ret;
-
- ret = cpufreq_frequency_table_cpuinfo(policy, table);
- if (ret)
- return ret;
-
- policy->freq_table = table;
- return 0;
-}
-EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
-
int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy)
{
int ret;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 6d084c61ee25..17e566afbb41 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -26,7 +26,6 @@
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/fs.h>
-#include <linux/debugfs.h>
#include <linux/acpi.h>
#include <linux/vmalloc.h>
#include <trace/events/power.h>
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index 959a1dbe3835..b4dbc77459b6 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -159,13 +159,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
priv->domain_id = handle->perf_ops->device_domain_id(cpu_dev);
policy->driver_data = priv;
-
- ret = cpufreq_table_validate_and_show(policy, freq_table);
- if (ret) {
- dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__,
- ret);
- goto out_free_cpufreq_table;
- }
+ policy->freq_table = freq_table;
/* SCMI allows DVFS request for any domain from any CPU */
policy->dvfs_possible_from_any_cpu = true;
@@ -179,8 +173,6 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
policy->fast_switch_possible = true;
return 0;
-out_free_cpufreq_table:
- dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_free_priv:
kfree(priv);
out_free_opp:
diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
index a099b7bf74cd..6ba709b6f095 100644
--- a/drivers/cpufreq/ti-cpufreq.c
+++ b/drivers/cpufreq/ti-cpufreq.c
@@ -304,7 +304,7 @@ static struct platform_driver ti_cpufreq_driver = {
.name = "ti-cpufreq",
},
};
-module_platform_driver(ti_cpufreq_driver);
+builtin_platform_driver(ti_cpufreq_driver);
MODULE_DESCRIPTION("TI CPUFreq/OPP hw-supported driver");
MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>");
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 0003e9a02637..6df894d65d9e 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -272,12 +272,18 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
*
* @drv: the cpuidle driver
* @dev: the cpuidle device
+ * @stop_tick: indication on whether or not to stop the tick
*
* Returns the index of the idle state. The return value must not be negative.
+ *
+ * The memory location pointed to by @stop_tick is expected to be written the
+ * 'false' boolean value if the scheduler tick should not be stopped before
+ * entering the returned state.
*/
-int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
+int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
+ bool *stop_tick)
{
- return cpuidle_curr_governor->select(drv, dev);
+ return cpuidle_curr_governor->select(drv, dev, stop_tick);
}
/**
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index 1ad8745fd6d6..b24883f85c99 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -63,9 +63,10 @@ static inline void ladder_do_selection(struct ladder_device *ldev,
* ladder_select_state - selects the next state to enter
* @drv: cpuidle driver
* @dev: the CPU
+ * @dummy: not used
*/
static int ladder_select_state(struct cpuidle_driver *drv,
- struct cpuidle_device *dev)
+ struct cpuidle_device *dev, bool *dummy)
{
struct ladder_device *ldev = this_cpu_ptr(&ladder_devices);
struct device *device = get_cpu_device(dev->cpu);
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index aa390404e85f..1bfe03ceb236 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -123,6 +123,7 @@
struct menu_device {
int last_state_idx;
int needs_update;
+ int tick_wakeup;
unsigned int next_timer_us;
unsigned int predicted_us;
@@ -279,8 +280,10 @@ again:
* menu_select - selects the next idle state to enter
* @drv: cpuidle driver containing state data
* @dev: the CPU
+ * @stop_tick: indication on whether or not to stop the tick
*/
-static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
+static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
+ bool *stop_tick)
{
struct menu_device *data = this_cpu_ptr(&menu_devices);
struct device *device = get_cpu_device(dev->cpu);
@@ -292,6 +295,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
unsigned int expected_interval;
unsigned long nr_iowaiters, cpu_load;
int resume_latency = dev_pm_qos_raw_read_value(device);
+ ktime_t delta_next;
if (data->needs_update) {
menu_update(drv, dev);
@@ -303,11 +307,13 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
latency_req = resume_latency;
/* Special case when user has set very strict latency requirement */
- if (unlikely(latency_req == 0))
+ if (unlikely(latency_req == 0)) {
+ *stop_tick = false;
return 0;
+ }
/* determine the expected residency time, round up */
- data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length());
+ data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length(&delta_next));
get_iowait_load(&nr_iowaiters, &cpu_load);
data->bucket = which_bucket(data->next_timer_us, nr_iowaiters);
@@ -346,14 +352,30 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
*/
data->predicted_us = min(data->predicted_us, expected_interval);
- /*
- * Use the performance multiplier and the user-configurable
- * latency_req to determine the maximum exit latency.
- */
- interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load);
- if (latency_req > interactivity_req)
- latency_req = interactivity_req;
+ if (tick_nohz_tick_stopped()) {
+ /*
+ * If the tick is already stopped, the cost of possible short
+ * idle duration misprediction is much higher, because the CPU
+ * may be stuck in a shallow idle state for a long time as a
+ * result of it. In that case say we might mispredict and try
+ * to force the CPU into a state for which we would have stopped
+ * the tick, unless a timer is going to expire really soon
+ * anyway.
+ */
+ if (data->predicted_us < TICK_USEC)
+ data->predicted_us = min_t(unsigned int, TICK_USEC,
+ ktime_to_us(delta_next));
+ } else {
+ /*
+ * Use the performance multiplier and the user-configurable
+ * latency_req to determine the maximum exit latency.
+ */
+ interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load);
+ if (latency_req > interactivity_req)
+ latency_req = interactivity_req;
+ }
+ expected_interval = data->predicted_us;
/*
* Find the idle state with the lowest power while satisfying
* our constraints.
@@ -369,15 +391,52 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
idx = i; /* first enabled state */
if (s->target_residency > data->predicted_us)
break;
- if (s->exit_latency > latency_req)
+ if (s->exit_latency > latency_req) {
+ /*
+ * If we break out of the loop for latency reasons, use
+ * the target residency of the selected state as the
+ * expected idle duration so that the tick is retained
+ * as long as that target residency is low enough.
+ */
+ expected_interval = drv->states[idx].target_residency;
break;
-
+ }
idx = i;
}
if (idx == -1)
idx = 0; /* No states enabled. Must use 0. */
+ /*
+ * Don't stop the tick if the selected state is a polling one or if the
+ * expected idle duration is shorter than the tick period length.
+ */
+ if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) ||
+ expected_interval < TICK_USEC) {
+ unsigned int delta_next_us = ktime_to_us(delta_next);
+
+ *stop_tick = false;
+
+ if (!tick_nohz_tick_stopped() && idx > 0 &&
+ drv->states[idx].target_residency > delta_next_us) {
+ /*
+ * The tick is not going to be stopped and the target
+ * residency of the state to be returned is not within
+ * the time until the next timer event including the
+ * tick, so try to correct that.
+ */
+ for (i = idx - 1; i >= 0; i--) {
+ if (drv->states[i].disabled ||
+ dev->states_usage[i].disable)
+ continue;
+
+ idx = i;
+ if (drv->states[i].target_residency <= delta_next_us)
+ break;
+ }
+ }
+ }
+
data->last_state_idx = idx;
return data->last_state_idx;
@@ -397,6 +456,7 @@ static void menu_reflect(struct cpuidle_device *dev, int index)
data->last_state_idx = index;
data->needs_update = 1;
+ data->tick_wakeup = tick_nohz_idle_got_tick();
}
/**
@@ -427,14 +487,27 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
* assume the state was never reached and the exit latency is 0.
*/
- /* measured value */
- measured_us = cpuidle_get_last_residency(dev);
-
- /* Deduct exit latency */
- if (measured_us > 2 * target->exit_latency)
- measured_us -= target->exit_latency;
- else
- measured_us /= 2;
+ if (data->tick_wakeup && data->next_timer_us > TICK_USEC) {
+ /*
+ * The nohz code said that there wouldn't be any events within
+ * the tick boundary (if the tick was stopped), but the idle
+ * duration predictor had a differing opinion. Since the CPU
+ * was woken up by a tick (that wasn't stopped after all), the
+ * predictor was not quite right, so assume that the CPU could
+ * have been idle long (but not forever) to help the idle
+ * duration predictor do a better job next time.
+ */
+ measured_us = 9 * MAX_INTERESTING / 10;
+ } else {
+ /* measured value */
+ measured_us = cpuidle_get_last_residency(dev);
+
+ /* Deduct exit latency */
+ if (measured_us > 2 * target->exit_latency)
+ measured_us -= target->exit_latency;
+ else
+ measured_us /= 2;
+ }
/* Make sure our coefficients do not exceed unity */
if (measured_us > data->next_timer_us)
diff --git a/drivers/dax/Kconfig b/drivers/dax/Kconfig
index b79aa8f7a497..e0700bf4893a 100644
--- a/drivers/dax/Kconfig
+++ b/drivers/dax/Kconfig
@@ -1,3 +1,7 @@
+config DAX_DRIVER
+ select DAX
+ bool
+
menuconfig DAX
tristate "DAX: direct access to differentiated memory"
select SRCU
@@ -16,7 +20,6 @@ config DEV_DAX
baseline memory pool. Mappings of a /dev/daxX.Y device impose
restrictions that make the mapping behavior deterministic.
-
config DEV_DAX_PMEM
tristate "PMEM DAX: direct access to persistent memory"
depends on LIBNVDIMM && NVDIMM_DAX && DEV_DAX
diff --git a/drivers/dax/device.c b/drivers/dax/device.c
index 0b61f48f21a6..be8606457f27 100644
--- a/drivers/dax/device.c
+++ b/drivers/dax/device.c
@@ -257,8 +257,8 @@ static int __dev_dax_pte_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
dax_region = dev_dax->region;
if (dax_region->align > PAGE_SIZE) {
- dev_dbg(dev, "%s: alignment (%#x) > fault size (%#x)\n",
- __func__, dax_region->align, fault_size);
+ dev_dbg(dev, "alignment (%#x) > fault size (%#x)\n",
+ dax_region->align, fault_size);
return VM_FAULT_SIGBUS;
}
@@ -267,8 +267,7 @@ static int __dev_dax_pte_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
phys = dax_pgoff_to_phys(dev_dax, vmf->pgoff, PAGE_SIZE);
if (phys == -1) {
- dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,
- vmf->pgoff);
+ dev_dbg(dev, "pgoff_to_phys(%#lx) failed\n", vmf->pgoff);
return VM_FAULT_SIGBUS;
}
@@ -299,14 +298,14 @@ static int __dev_dax_pmd_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
dax_region = dev_dax->region;
if (dax_region->align > PMD_SIZE) {
- dev_dbg(dev, "%s: alignment (%#x) > fault size (%#x)\n",
- __func__, dax_region->align, fault_size);
+ dev_dbg(dev, "alignment (%#x) > fault size (%#x)\n",
+ dax_region->align, fault_size);
return VM_FAULT_SIGBUS;
}
/* dax pmd mappings require pfn_t_devmap() */
if ((dax_region->pfn_flags & (PFN_DEV|PFN_MAP)) != (PFN_DEV|PFN_MAP)) {
- dev_dbg(dev, "%s: region lacks devmap flags\n", __func__);
+ dev_dbg(dev, "region lacks devmap flags\n");
return VM_FAULT_SIGBUS;
}
@@ -323,8 +322,7 @@ static int __dev_dax_pmd_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
pgoff = linear_page_index(vmf->vma, pmd_addr);
phys = dax_pgoff_to_phys(dev_dax, pgoff, PMD_SIZE);
if (phys == -1) {
- dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,
- pgoff);
+ dev_dbg(dev, "pgoff_to_phys(%#lx) failed\n", pgoff);
return VM_FAULT_SIGBUS;
}
@@ -351,14 +349,14 @@ static int __dev_dax_pud_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
dax_region = dev_dax->region;
if (dax_region->align > PUD_SIZE) {
- dev_dbg(dev, "%s: alignment (%#x) > fault size (%#x)\n",
- __func__, dax_region->align, fault_size);
+ dev_dbg(dev, "alignment (%#x) > fault size (%#x)\n",
+ dax_region->align, fault_size);
return VM_FAULT_SIGBUS;
}
/* dax pud mappings require pfn_t_devmap() */
if ((dax_region->pfn_flags & (PFN_DEV|PFN_MAP)) != (PFN_DEV|PFN_MAP)) {
- dev_dbg(dev, "%s: region lacks devmap flags\n", __func__);
+ dev_dbg(dev, "region lacks devmap flags\n");
return VM_FAULT_SIGBUS;
}
@@ -375,8 +373,7 @@ static int __dev_dax_pud_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
pgoff = linear_page_index(vmf->vma, pud_addr);
phys = dax_pgoff_to_phys(dev_dax, pgoff, PUD_SIZE);
if (phys == -1) {
- dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,
- pgoff);
+ dev_dbg(dev, "pgoff_to_phys(%#lx) failed\n", pgoff);
return VM_FAULT_SIGBUS;
}
@@ -399,9 +396,8 @@ static int dev_dax_huge_fault(struct vm_fault *vmf,
struct file *filp = vmf->vma->vm_file;
struct dev_dax *dev_dax = filp->private_data;
- dev_dbg(&dev_dax->dev, "%s: %s: %s (%#lx - %#lx) size = %d\n", __func__,
- current->comm, (vmf->flags & FAULT_FLAG_WRITE)
- ? "write" : "read",
+ dev_dbg(&dev_dax->dev, "%s: %s (%#lx - %#lx) size = %d\n", current->comm,
+ (vmf->flags & FAULT_FLAG_WRITE) ? "write" : "read",
vmf->vma->vm_start, vmf->vma->vm_end, pe_size);
id = dax_read_lock();
@@ -460,7 +456,7 @@ static int dax_mmap(struct file *filp, struct vm_area_struct *vma)
struct dev_dax *dev_dax = filp->private_data;
int rc, id;
- dev_dbg(&dev_dax->dev, "%s\n", __func__);
+ dev_dbg(&dev_dax->dev, "trace\n");
/*
* We lock to check dax_dev liveness and will re-check at
@@ -518,7 +514,7 @@ static int dax_open(struct inode *inode, struct file *filp)
struct inode *__dax_inode = dax_inode(dax_dev);
struct dev_dax *dev_dax = dax_get_private(dax_dev);
- dev_dbg(&dev_dax->dev, "%s\n", __func__);
+ dev_dbg(&dev_dax->dev, "trace\n");
inode->i_mapping = __dax_inode->i_mapping;
inode->i_mapping->host = __dax_inode;
filp->f_mapping = inode->i_mapping;
@@ -533,7 +529,7 @@ static int dax_release(struct inode *inode, struct file *filp)
{
struct dev_dax *dev_dax = filp->private_data;
- dev_dbg(&dev_dax->dev, "%s\n", __func__);
+ dev_dbg(&dev_dax->dev, "trace\n");
return 0;
}
@@ -575,7 +571,7 @@ static void unregister_dev_dax(void *dev)
struct inode *inode = dax_inode(dax_dev);
struct cdev *cdev = inode->i_cdev;
- dev_dbg(dev, "%s\n", __func__);
+ dev_dbg(dev, "trace\n");
kill_dev_dax(dev_dax);
cdev_device_del(cdev, dev);
diff --git a/drivers/dax/pmem.c b/drivers/dax/pmem.c
index 31b6ecce4c64..fd49b24fd6af 100644
--- a/drivers/dax/pmem.c
+++ b/drivers/dax/pmem.c
@@ -34,7 +34,7 @@ static void dax_pmem_percpu_release(struct percpu_ref *ref)
{
struct dax_pmem *dax_pmem = to_dax_pmem(ref);
- dev_dbg(dax_pmem->dev, "%s\n", __func__);
+ dev_dbg(dax_pmem->dev, "trace\n");
complete(&dax_pmem->cmp);
}
@@ -43,7 +43,7 @@ static void dax_pmem_percpu_exit(void *data)
struct percpu_ref *ref = data;
struct dax_pmem *dax_pmem = to_dax_pmem(ref);
- dev_dbg(dax_pmem->dev, "%s\n", __func__);
+ dev_dbg(dax_pmem->dev, "trace\n");
wait_for_completion(&dax_pmem->cmp);
percpu_ref_exit(ref);
}
@@ -53,7 +53,7 @@ static void dax_pmem_percpu_kill(void *data)
struct percpu_ref *ref = data;
struct dax_pmem *dax_pmem = to_dax_pmem(ref);
- dev_dbg(dax_pmem->dev, "%s\n", __func__);
+ dev_dbg(dax_pmem->dev, "trace\n");
percpu_ref_kill(ref);
}
@@ -150,17 +150,7 @@ static struct nd_device_driver dax_pmem_driver = {
.type = ND_DRIVER_DAX_PMEM,
};
-static int __init dax_pmem_init(void)
-{
- return nd_driver_register(&dax_pmem_driver);
-}
-module_init(dax_pmem_init);
-
-static void __exit dax_pmem_exit(void)
-{
- driver_unregister(&dax_pmem_driver.drv);
-}
-module_exit(dax_pmem_exit);
+module_nd_driver(dax_pmem_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Intel Corporation");
diff --git a/drivers/dax/super.c b/drivers/dax/super.c
index ecdc292aa4e4..2b2332b605e4 100644
--- a/drivers/dax/super.c
+++ b/drivers/dax/super.c
@@ -124,10 +124,19 @@ int __bdev_dax_supported(struct super_block *sb, int blocksize)
return len < 0 ? len : -EIO;
}
- if ((IS_ENABLED(CONFIG_FS_DAX_LIMITED) && pfn_t_special(pfn))
- || pfn_t_devmap(pfn))
+ if (IS_ENABLED(CONFIG_FS_DAX_LIMITED) && pfn_t_special(pfn)) {
+ /*
+ * An arch that has enabled the pmem api should also
+ * have its drivers support pfn_t_devmap()
+ *
+ * This is a developer warning and should not trigger in
+ * production. dax_flush() will crash since it depends
+ * on being able to do (page_address(pfn_to_page())).
+ */
+ WARN_ON(IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API));
+ } else if (pfn_t_devmap(pfn)) {
/* pass */;
- else {
+ } else {
pr_debug("VFS (%s): error: dax support not enabled\n",
sb->s_id);
return -EOPNOTSUPP;
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 27df3e2837fd..6d61cd023633 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -187,6 +187,16 @@ config DMA_SUN6I
help
Support for the DMA engine first found in Allwinner A31 SoCs.
+config DW_AXI_DMAC
+ tristate "Synopsys DesignWare AXI DMA support"
+ depends on OF || COMPILE_TEST
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+ Enable support for Synopsys DesignWare AXI DMA controller.
+ NOTE: This driver wasn't tested on 64 bit platform because
+ of lack 64 bit platform with Synopsys DW AXI DMAC.
+
config EP93XX_DMA
bool "Cirrus Logic EP93xx DMA support"
depends on ARCH_EP93XX || COMPILE_TEST
@@ -633,6 +643,8 @@ config ZX_DMA
# driver files
source "drivers/dma/bestcomm/Kconfig"
+source "drivers/dma/mediatek/Kconfig"
+
source "drivers/dma/qcom/Kconfig"
source "drivers/dma/dw/Kconfig"
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index b9dca8a0e142..0f62a4d49aab 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_DMA_OMAP) += omap-dma.o
obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
obj-$(CONFIG_DMA_SUN4I) += sun4i-dma.o
obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o
+obj-$(CONFIG_DW_AXI_DMAC) += dw-axi-dmac/
obj-$(CONFIG_DW_DMAC_CORE) += dw/
obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
obj-$(CONFIG_FSL_DMA) += fsldma.o
@@ -75,5 +76,6 @@ obj-$(CONFIG_XGENE_DMA) += xgene-dma.o
obj-$(CONFIG_ZX_DMA) += zx_dma.o
obj-$(CONFIG_ST_FDMA) += st_fdma.o
+obj-y += mediatek/
obj-y += qcom/
obj-y += xilinx/
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index c00e3923d7d8..94236ec9d410 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -1471,10 +1471,10 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
rmb();
- initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
- rmb();
cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
rmb();
+ initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
+ rmb();
cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
rmb();
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 80cc2be6483c..b9339524d5bd 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -74,7 +74,11 @@ MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
static bool noverify;
module_param(noverify, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(noverify, "Disable random data setup and verification");
+MODULE_PARM_DESC(noverify, "Disable data verification (default: verify)");
+
+static bool norandom;
+module_param(norandom, bool, 0644);
+MODULE_PARM_DESC(norandom, "Disable random offset setup (default: random)");
static bool verbose;
module_param(verbose, bool, S_IRUGO | S_IWUSR);
@@ -103,6 +107,7 @@ struct dmatest_params {
unsigned int pq_sources;
int timeout;
bool noverify;
+ bool norandom;
};
/**
@@ -575,7 +580,7 @@ static int dmatest_func(void *data)
break;
}
- if (params->noverify)
+ if (params->norandom)
len = params->buf_size;
else
len = dmatest_random() % params->buf_size + 1;
@@ -586,17 +591,19 @@ static int dmatest_func(void *data)
total_len += len;
- if (params->noverify) {
+ if (params->norandom) {
src_off = 0;
dst_off = 0;
} else {
- start = ktime_get();
src_off = dmatest_random() % (params->buf_size - len + 1);
dst_off = dmatest_random() % (params->buf_size - len + 1);
src_off = (src_off >> align) << align;
dst_off = (dst_off >> align) << align;
+ }
+ if (!params->noverify) {
+ start = ktime_get();
dmatest_init_srcs(thread->srcs, src_off, len,
params->buf_size, is_memset);
dmatest_init_dsts(thread->dsts, dst_off, len,
@@ -975,6 +982,7 @@ static void run_threaded_test(struct dmatest_info *info)
params->pq_sources = pq_sources;
params->timeout = timeout;
params->noverify = noverify;
+ params->norandom = norandom;
request_channels(info, DMA_MEMCPY);
request_channels(info, DMA_MEMSET);
diff --git a/drivers/dma/dw-axi-dmac/Makefile b/drivers/dma/dw-axi-dmac/Makefile
new file mode 100644
index 000000000000..4bfa462005be
--- /dev/null
+++ b/drivers/dma/dw-axi-dmac/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_DW_AXI_DMAC) += dw-axi-dmac-platform.o
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
new file mode 100644
index 000000000000..c4eb55e3011c
--- /dev/null
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -0,0 +1,1008 @@
+// SPDX-License-Identifier: GPL-2.0
+// (C) 2017-2018 Synopsys, Inc. (www.synopsys.com)
+
+/*
+ * Synopsys DesignWare AXI DMA Controller driver.
+ *
+ * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
+#include "dw-axi-dmac.h"
+#include "../dmaengine.h"
+#include "../virt-dma.h"
+
+/*
+ * The set of bus widths supported by the DMA controller. DW AXI DMAC supports
+ * master data bus width up to 512 bits (for both AXI master interfaces), but
+ * it depends on IP block configurarion.
+ */
+#define AXI_DMA_BUSWIDTHS \
+ (DMA_SLAVE_BUSWIDTH_1_BYTE | \
+ DMA_SLAVE_BUSWIDTH_2_BYTES | \
+ DMA_SLAVE_BUSWIDTH_4_BYTES | \
+ DMA_SLAVE_BUSWIDTH_8_BYTES | \
+ DMA_SLAVE_BUSWIDTH_16_BYTES | \
+ DMA_SLAVE_BUSWIDTH_32_BYTES | \
+ DMA_SLAVE_BUSWIDTH_64_BYTES)
+
+static inline void
+axi_dma_iowrite32(struct axi_dma_chip *chip, u32 reg, u32 val)
+{
+ iowrite32(val, chip->regs + reg);
+}
+
+static inline u32 axi_dma_ioread32(struct axi_dma_chip *chip, u32 reg)
+{
+ return ioread32(chip->regs + reg);
+}
+
+static inline void
+axi_chan_iowrite32(struct axi_dma_chan *chan, u32 reg, u32 val)
+{
+ iowrite32(val, chan->chan_regs + reg);
+}
+
+static inline u32 axi_chan_ioread32(struct axi_dma_chan *chan, u32 reg)
+{
+ return ioread32(chan->chan_regs + reg);
+}
+
+static inline void
+axi_chan_iowrite64(struct axi_dma_chan *chan, u32 reg, u64 val)
+{
+ /*
+ * We split one 64 bit write for two 32 bit write as some HW doesn't
+ * support 64 bit access.
+ */
+ iowrite32(lower_32_bits(val), chan->chan_regs + reg);
+ iowrite32(upper_32_bits(val), chan->chan_regs + reg + 4);
+}
+
+static inline void axi_dma_disable(struct axi_dma_chip *chip)
+{
+ u32 val;
+
+ val = axi_dma_ioread32(chip, DMAC_CFG);
+ val &= ~DMAC_EN_MASK;
+ axi_dma_iowrite32(chip, DMAC_CFG, val);
+}
+
+static inline void axi_dma_enable(struct axi_dma_chip *chip)
+{
+ u32 val;
+
+ val = axi_dma_ioread32(chip, DMAC_CFG);
+ val |= DMAC_EN_MASK;
+ axi_dma_iowrite32(chip, DMAC_CFG, val);
+}
+
+static inline void axi_dma_irq_disable(struct axi_dma_chip *chip)
+{
+ u32 val;
+
+ val = axi_dma_ioread32(chip, DMAC_CFG);
+ val &= ~INT_EN_MASK;
+ axi_dma_iowrite32(chip, DMAC_CFG, val);
+}
+
+static inline void axi_dma_irq_enable(struct axi_dma_chip *chip)
+{
+ u32 val;
+
+ val = axi_dma_ioread32(chip, DMAC_CFG);
+ val |= INT_EN_MASK;
+ axi_dma_iowrite32(chip, DMAC_CFG, val);
+}
+
+static inline void axi_chan_irq_disable(struct axi_dma_chan *chan, u32 irq_mask)
+{
+ u32 val;
+
+ if (likely(irq_mask == DWAXIDMAC_IRQ_ALL)) {
+ axi_chan_iowrite32(chan, CH_INTSTATUS_ENA, DWAXIDMAC_IRQ_NONE);
+ } else {
+ val = axi_chan_ioread32(chan, CH_INTSTATUS_ENA);
+ val &= ~irq_mask;
+ axi_chan_iowrite32(chan, CH_INTSTATUS_ENA, val);
+ }
+}
+
+static inline void axi_chan_irq_set(struct axi_dma_chan *chan, u32 irq_mask)
+{
+ axi_chan_iowrite32(chan, CH_INTSTATUS_ENA, irq_mask);
+}
+
+static inline void axi_chan_irq_sig_set(struct axi_dma_chan *chan, u32 irq_mask)
+{
+ axi_chan_iowrite32(chan, CH_INTSIGNAL_ENA, irq_mask);
+}
+
+static inline void axi_chan_irq_clear(struct axi_dma_chan *chan, u32 irq_mask)
+{
+ axi_chan_iowrite32(chan, CH_INTCLEAR, irq_mask);
+}
+
+static inline u32 axi_chan_irq_read(struct axi_dma_chan *chan)
+{
+ return axi_chan_ioread32(chan, CH_INTSTATUS);
+}
+
+static inline void axi_chan_disable(struct axi_dma_chan *chan)
+{
+ u32 val;
+
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
+ val |= BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+}
+
+static inline void axi_chan_enable(struct axi_dma_chan *chan)
+{
+ u32 val;
+
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+}
+
+static inline bool axi_chan_is_hw_enable(struct axi_dma_chan *chan)
+{
+ u32 val;
+
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+
+ return !!(val & (BIT(chan->id) << DMAC_CHAN_EN_SHIFT));
+}
+
+static void axi_dma_hw_init(struct axi_dma_chip *chip)
+{
+ u32 i;
+
+ for (i = 0; i < chip->dw->hdata->nr_channels; i++) {
+ axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
+ axi_chan_disable(&chip->dw->chan[i]);
+ }
+}
+
+static u32 axi_chan_get_xfer_width(struct axi_dma_chan *chan, dma_addr_t src,
+ dma_addr_t dst, size_t len)
+{
+ u32 max_width = chan->chip->dw->hdata->m_data_width;
+
+ return __ffs(src | dst | len | BIT(max_width));
+}
+
+static inline const char *axi_chan_name(struct axi_dma_chan *chan)
+{
+ return dma_chan_name(&chan->vc.chan);
+}
+
+static struct axi_dma_desc *axi_desc_get(struct axi_dma_chan *chan)
+{
+ struct dw_axi_dma *dw = chan->chip->dw;
+ struct axi_dma_desc *desc;
+ dma_addr_t phys;
+
+ desc = dma_pool_zalloc(dw->desc_pool, GFP_NOWAIT, &phys);
+ if (unlikely(!desc)) {
+ dev_err(chan2dev(chan), "%s: not enough descriptors available\n",
+ axi_chan_name(chan));
+ return NULL;
+ }
+
+ atomic_inc(&chan->descs_allocated);
+ INIT_LIST_HEAD(&desc->xfer_list);
+ desc->vd.tx.phys = phys;
+ desc->chan = chan;
+
+ return desc;
+}
+
+static void axi_desc_put(struct axi_dma_desc *desc)
+{
+ struct axi_dma_chan *chan = desc->chan;
+ struct dw_axi_dma *dw = chan->chip->dw;
+ struct axi_dma_desc *child, *_next;
+ unsigned int descs_put = 0;
+
+ list_for_each_entry_safe(child, _next, &desc->xfer_list, xfer_list) {
+ list_del(&child->xfer_list);
+ dma_pool_free(dw->desc_pool, child, child->vd.tx.phys);
+ descs_put++;
+ }
+
+ dma_pool_free(dw->desc_pool, desc, desc->vd.tx.phys);
+ descs_put++;
+
+ atomic_sub(descs_put, &chan->descs_allocated);
+ dev_vdbg(chan2dev(chan), "%s: %d descs put, %d still allocated\n",
+ axi_chan_name(chan), descs_put,
+ atomic_read(&chan->descs_allocated));
+}
+
+static void vchan_desc_put(struct virt_dma_desc *vdesc)
+{
+ axi_desc_put(vd_to_axi_desc(vdesc));
+}
+
+static enum dma_status
+dma_chan_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
+ enum dma_status ret;
+
+ ret = dma_cookie_status(dchan, cookie, txstate);
+
+ if (chan->is_paused && ret == DMA_IN_PROGRESS)
+ ret = DMA_PAUSED;
+
+ return ret;
+}
+
+static void write_desc_llp(struct axi_dma_desc *desc, dma_addr_t adr)
+{
+ desc->lli.llp = cpu_to_le64(adr);
+}
+
+static void write_chan_llp(struct axi_dma_chan *chan, dma_addr_t adr)
+{
+ axi_chan_iowrite64(chan, CH_LLP, adr);
+}
+
+/* Called in chan locked context */
+static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
+ struct axi_dma_desc *first)
+{
+ u32 priority = chan->chip->dw->hdata->priority[chan->id];
+ u32 reg, irq_mask;
+ u8 lms = 0; /* Select AXI0 master for LLI fetching */
+
+ if (unlikely(axi_chan_is_hw_enable(chan))) {
+ dev_err(chan2dev(chan), "%s is non-idle!\n",
+ axi_chan_name(chan));
+
+ return;
+ }
+
+ axi_dma_enable(chan->chip);
+
+ reg = (DWAXIDMAC_MBLK_TYPE_LL << CH_CFG_L_DST_MULTBLK_TYPE_POS |
+ DWAXIDMAC_MBLK_TYPE_LL << CH_CFG_L_SRC_MULTBLK_TYPE_POS);
+ axi_chan_iowrite32(chan, CH_CFG_L, reg);
+
+ reg = (DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC << CH_CFG_H_TT_FC_POS |
+ priority << CH_CFG_H_PRIORITY_POS |
+ DWAXIDMAC_HS_SEL_HW << CH_CFG_H_HS_SEL_DST_POS |
+ DWAXIDMAC_HS_SEL_HW << CH_CFG_H_HS_SEL_SRC_POS);
+ axi_chan_iowrite32(chan, CH_CFG_H, reg);
+
+ write_chan_llp(chan, first->vd.tx.phys | lms);
+
+ irq_mask = DWAXIDMAC_IRQ_DMA_TRF | DWAXIDMAC_IRQ_ALL_ERR;
+ axi_chan_irq_sig_set(chan, irq_mask);
+
+ /* Generate 'suspend' status but don't generate interrupt */
+ irq_mask |= DWAXIDMAC_IRQ_SUSPENDED;
+ axi_chan_irq_set(chan, irq_mask);
+
+ axi_chan_enable(chan);
+}
+
+static void axi_chan_start_first_queued(struct axi_dma_chan *chan)
+{
+ struct axi_dma_desc *desc;
+ struct virt_dma_desc *vd;
+
+ vd = vchan_next_desc(&chan->vc);
+ if (!vd)
+ return;
+
+ desc = vd_to_axi_desc(vd);
+ dev_vdbg(chan2dev(chan), "%s: started %u\n", axi_chan_name(chan),
+ vd->tx.cookie);
+ axi_chan_block_xfer_start(chan, desc);
+}
+
+static void dma_chan_issue_pending(struct dma_chan *dchan)
+{
+ struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->vc.lock, flags);
+ if (vchan_issue_pending(&chan->vc))
+ axi_chan_start_first_queued(chan);
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
+}
+
+static int dma_chan_alloc_chan_resources(struct dma_chan *dchan)
+{
+ struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
+
+ /* ASSERT: channel is idle */
+ if (axi_chan_is_hw_enable(chan)) {
+ dev_err(chan2dev(chan), "%s is non-idle!\n",
+ axi_chan_name(chan));
+ return -EBUSY;
+ }
+
+ dev_vdbg(dchan2dev(dchan), "%s: allocating\n", axi_chan_name(chan));
+
+ pm_runtime_get(chan->chip->dev);
+
+ return 0;
+}
+
+static void dma_chan_free_chan_resources(struct dma_chan *dchan)
+{
+ struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
+
+ /* ASSERT: channel is idle */
+ if (axi_chan_is_hw_enable(chan))
+ dev_err(dchan2dev(dchan), "%s is non-idle!\n",
+ axi_chan_name(chan));
+
+ axi_chan_disable(chan);
+ axi_chan_irq_disable(chan, DWAXIDMAC_IRQ_ALL);
+
+ vchan_free_chan_resources(&chan->vc);
+
+ dev_vdbg(dchan2dev(dchan),
+ "%s: free resources, descriptor still allocated: %u\n",
+ axi_chan_name(chan), atomic_read(&chan->descs_allocated));
+
+ pm_runtime_put(chan->chip->dev);
+}
+
+/*
+ * If DW_axi_dmac sees CHx_CTL.ShadowReg_Or_LLI_Last bit of the fetched LLI
+ * as 1, it understands that the current block is the final block in the
+ * transfer and completes the DMA transfer operation at the end of current
+ * block transfer.
+ */
+static void set_desc_last(struct axi_dma_desc *desc)
+{
+ u32 val;
+
+ val = le32_to_cpu(desc->lli.ctl_hi);
+ val |= CH_CTL_H_LLI_LAST;
+ desc->lli.ctl_hi = cpu_to_le32(val);
+}
+
+static void write_desc_sar(struct axi_dma_desc *desc, dma_addr_t adr)
+{
+ desc->lli.sar = cpu_to_le64(adr);
+}
+
+static void write_desc_dar(struct axi_dma_desc *desc, dma_addr_t adr)
+{
+ desc->lli.dar = cpu_to_le64(adr);
+}
+
+static void set_desc_src_master(struct axi_dma_desc *desc)
+{
+ u32 val;
+
+ /* Select AXI0 for source master */
+ val = le32_to_cpu(desc->lli.ctl_lo);
+ val &= ~CH_CTL_L_SRC_MAST;
+ desc->lli.ctl_lo = cpu_to_le32(val);
+}
+
+static void set_desc_dest_master(struct axi_dma_desc *desc)
+{
+ u32 val;
+
+ /* Select AXI1 for source master if available */
+ val = le32_to_cpu(desc->lli.ctl_lo);
+ if (desc->chan->chip->dw->hdata->nr_masters > 1)
+ val |= CH_CTL_L_DST_MAST;
+ else
+ val &= ~CH_CTL_L_DST_MAST;
+
+ desc->lli.ctl_lo = cpu_to_le32(val);
+}
+
+static struct dma_async_tx_descriptor *
+dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr,
+ dma_addr_t src_adr, size_t len, unsigned long flags)
+{
+ struct axi_dma_desc *first = NULL, *desc = NULL, *prev = NULL;
+ struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
+ size_t block_ts, max_block_ts, xfer_len;
+ u32 xfer_width, reg;
+ u8 lms = 0; /* Select AXI0 master for LLI fetching */
+
+ dev_dbg(chan2dev(chan), "%s: memcpy: src: %pad dst: %pad length: %zd flags: %#lx",
+ axi_chan_name(chan), &src_adr, &dst_adr, len, flags);
+
+ max_block_ts = chan->chip->dw->hdata->block_size[chan->id];
+
+ while (len) {
+ xfer_len = len;
+
+ /*
+ * Take care for the alignment.
+ * Actually source and destination widths can be different, but
+ * make them same to be simpler.
+ */
+ xfer_width = axi_chan_get_xfer_width(chan, src_adr, dst_adr, xfer_len);
+
+ /*
+ * block_ts indicates the total number of data of width
+ * to be transferred in a DMA block transfer.
+ * BLOCK_TS register should be set to block_ts - 1
+ */
+ block_ts = xfer_len >> xfer_width;
+ if (block_ts > max_block_ts) {
+ block_ts = max_block_ts;
+ xfer_len = max_block_ts << xfer_width;
+ }
+
+ desc = axi_desc_get(chan);
+ if (unlikely(!desc))
+ goto err_desc_get;
+
+ write_desc_sar(desc, src_adr);
+ write_desc_dar(desc, dst_adr);
+ desc->lli.block_ts_lo = cpu_to_le32(block_ts - 1);
+
+ reg = CH_CTL_H_LLI_VALID;
+ if (chan->chip->dw->hdata->restrict_axi_burst_len) {
+ u32 burst_len = chan->chip->dw->hdata->axi_rw_burst_len;
+
+ reg |= (CH_CTL_H_ARLEN_EN |
+ burst_len << CH_CTL_H_ARLEN_POS |
+ CH_CTL_H_AWLEN_EN |
+ burst_len << CH_CTL_H_AWLEN_POS);
+ }
+ desc->lli.ctl_hi = cpu_to_le32(reg);
+
+ reg = (DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
+ DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS |
+ xfer_width << CH_CTL_L_DST_WIDTH_POS |
+ xfer_width << CH_CTL_L_SRC_WIDTH_POS |
+ DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS |
+ DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS);
+ desc->lli.ctl_lo = cpu_to_le32(reg);
+
+ set_desc_src_master(desc);
+ set_desc_dest_master(desc);
+
+ /* Manage transfer list (xfer_list) */
+ if (!first) {
+ first = desc;
+ } else {
+ list_add_tail(&desc->xfer_list, &first->xfer_list);
+ write_desc_llp(prev, desc->vd.tx.phys | lms);
+ }
+ prev = desc;
+
+ /* update the length and addresses for the next loop cycle */
+ len -= xfer_len;
+ dst_adr += xfer_len;
+ src_adr += xfer_len;
+ }
+
+ /* Total len of src/dest sg == 0, so no descriptor were allocated */
+ if (unlikely(!first))
+ return NULL;
+
+ /* Set end-of-link to the last link descriptor of list */
+ set_desc_last(desc);
+
+ return vchan_tx_prep(&chan->vc, &first->vd, flags);
+
+err_desc_get:
+ axi_desc_put(first);
+ return NULL;
+}
+
+static void axi_chan_dump_lli(struct axi_dma_chan *chan,
+ struct axi_dma_desc *desc)
+{
+ dev_err(dchan2dev(&chan->vc.chan),
+ "SAR: 0x%llx DAR: 0x%llx LLP: 0x%llx BTS 0x%x CTL: 0x%x:%08x",
+ le64_to_cpu(desc->lli.sar),
+ le64_to_cpu(desc->lli.dar),
+ le64_to_cpu(desc->lli.llp),
+ le32_to_cpu(desc->lli.block_ts_lo),
+ le32_to_cpu(desc->lli.ctl_hi),
+ le32_to_cpu(desc->lli.ctl_lo));
+}
+
+static void axi_chan_list_dump_lli(struct axi_dma_chan *chan,
+ struct axi_dma_desc *desc_head)
+{
+ struct axi_dma_desc *desc;
+
+ axi_chan_dump_lli(chan, desc_head);
+ list_for_each_entry(desc, &desc_head->xfer_list, xfer_list)
+ axi_chan_dump_lli(chan, desc);
+}
+
+static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status)
+{
+ struct virt_dma_desc *vd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->vc.lock, flags);
+
+ axi_chan_disable(chan);
+
+ /* The bad descriptor currently is in the head of vc list */
+ vd = vchan_next_desc(&chan->vc);
+ /* Remove the completed descriptor from issued list */
+ list_del(&vd->node);
+
+ /* WARN about bad descriptor */
+ dev_err(chan2dev(chan),
+ "Bad descriptor submitted for %s, cookie: %d, irq: 0x%08x\n",
+ axi_chan_name(chan), vd->tx.cookie, status);
+ axi_chan_list_dump_lli(chan, vd_to_axi_desc(vd));
+
+ vchan_cookie_complete(vd);
+
+ /* Try to restart the controller */
+ axi_chan_start_first_queued(chan);
+
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
+}
+
+static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan)
+{
+ struct virt_dma_desc *vd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->vc.lock, flags);
+ if (unlikely(axi_chan_is_hw_enable(chan))) {
+ dev_err(chan2dev(chan), "BUG: %s caught DWAXIDMAC_IRQ_DMA_TRF, but channel not idle!\n",
+ axi_chan_name(chan));
+ axi_chan_disable(chan);
+ }
+
+ /* The completed descriptor currently is in the head of vc list */
+ vd = vchan_next_desc(&chan->vc);
+ /* Remove the completed descriptor from issued list before completing */
+ list_del(&vd->node);
+ vchan_cookie_complete(vd);
+
+ /* Submit queued descriptors after processing the completed ones */
+ axi_chan_start_first_queued(chan);
+
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
+}
+
+static irqreturn_t dw_axi_dma_interrupt(int irq, void *dev_id)
+{
+ struct axi_dma_chip *chip = dev_id;
+ struct dw_axi_dma *dw = chip->dw;
+ struct axi_dma_chan *chan;
+
+ u32 status, i;
+
+ /* Disable DMAC inerrupts. We'll enable them after processing chanels */
+ axi_dma_irq_disable(chip);
+
+ /* Poll, clear and process every chanel interrupt status */
+ for (i = 0; i < dw->hdata->nr_channels; i++) {
+ chan = &dw->chan[i];
+ status = axi_chan_irq_read(chan);
+ axi_chan_irq_clear(chan, status);
+
+ dev_vdbg(chip->dev, "%s %u IRQ status: 0x%08x\n",
+ axi_chan_name(chan), i, status);
+
+ if (status & DWAXIDMAC_IRQ_ALL_ERR)
+ axi_chan_handle_err(chan, status);
+ else if (status & DWAXIDMAC_IRQ_DMA_TRF)
+ axi_chan_block_xfer_complete(chan);
+ }
+
+ /* Re-enable interrupts */
+ axi_dma_irq_enable(chip);
+
+ return IRQ_HANDLED;
+}
+
+static int dma_chan_terminate_all(struct dma_chan *dchan)
+{
+ struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
+ unsigned long flags;
+ LIST_HEAD(head);
+
+ spin_lock_irqsave(&chan->vc.lock, flags);
+
+ axi_chan_disable(chan);
+
+ vchan_get_all_descriptors(&chan->vc, &head);
+
+ /*
+ * As vchan_dma_desc_free_list can access to desc_allocated list
+ * we need to call it in vc.lock context.
+ */
+ vchan_dma_desc_free_list(&chan->vc, &head);
+
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+ dev_vdbg(dchan2dev(dchan), "terminated: %s\n", axi_chan_name(chan));
+
+ return 0;
+}
+
+static int dma_chan_pause(struct dma_chan *dchan)
+{
+ struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
+ unsigned long flags;
+ unsigned int timeout = 20; /* timeout iterations */
+ u32 val;
+
+ spin_lock_irqsave(&chan->vc.lock, flags);
+
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+
+ do {
+ if (axi_chan_irq_read(chan) & DWAXIDMAC_IRQ_SUSPENDED)
+ break;
+
+ udelay(2);
+ } while (--timeout);
+
+ axi_chan_irq_clear(chan, DWAXIDMAC_IRQ_SUSPENDED);
+
+ chan->is_paused = true;
+
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+ return timeout ? 0 : -EAGAIN;
+}
+
+/* Called in chan locked context */
+static inline void axi_chan_resume(struct axi_dma_chan *chan)
+{
+ u32 val;
+
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
+ val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+
+ chan->is_paused = false;
+}
+
+static int dma_chan_resume(struct dma_chan *dchan)
+{
+ struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->vc.lock, flags);
+
+ if (chan->is_paused)
+ axi_chan_resume(chan);
+
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+ return 0;
+}
+
+static int axi_dma_suspend(struct axi_dma_chip *chip)
+{
+ axi_dma_irq_disable(chip);
+ axi_dma_disable(chip);
+
+ clk_disable_unprepare(chip->core_clk);
+ clk_disable_unprepare(chip->cfgr_clk);
+
+ return 0;
+}
+
+static int axi_dma_resume(struct axi_dma_chip *chip)
+{
+ int ret;
+
+ ret = clk_prepare_enable(chip->cfgr_clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_prepare_enable(chip->core_clk);
+ if (ret < 0)
+ return ret;
+
+ axi_dma_enable(chip);
+ axi_dma_irq_enable(chip);
+
+ return 0;
+}
+
+static int __maybe_unused axi_dma_runtime_suspend(struct device *dev)
+{
+ struct axi_dma_chip *chip = dev_get_drvdata(dev);
+
+ return axi_dma_suspend(chip);
+}
+
+static int __maybe_unused axi_dma_runtime_resume(struct device *dev)
+{
+ struct axi_dma_chip *chip = dev_get_drvdata(dev);
+
+ return axi_dma_resume(chip);
+}
+
+static int parse_device_properties(struct axi_dma_chip *chip)
+{
+ struct device *dev = chip->dev;
+ u32 tmp, carr[DMAC_MAX_CHANNELS];
+ int ret;
+
+ ret = device_property_read_u32(dev, "dma-channels", &tmp);
+ if (ret)
+ return ret;
+ if (tmp == 0 || tmp > DMAC_MAX_CHANNELS)
+ return -EINVAL;
+
+ chip->dw->hdata->nr_channels = tmp;
+
+ ret = device_property_read_u32(dev, "snps,dma-masters", &tmp);
+ if (ret)
+ return ret;
+ if (tmp == 0 || tmp > DMAC_MAX_MASTERS)
+ return -EINVAL;
+
+ chip->dw->hdata->nr_masters = tmp;
+
+ ret = device_property_read_u32(dev, "snps,data-width", &tmp);
+ if (ret)
+ return ret;
+ if (tmp > DWAXIDMAC_TRANS_WIDTH_MAX)
+ return -EINVAL;
+
+ chip->dw->hdata->m_data_width = tmp;
+
+ ret = device_property_read_u32_array(dev, "snps,block-size", carr,
+ chip->dw->hdata->nr_channels);
+ if (ret)
+ return ret;
+ for (tmp = 0; tmp < chip->dw->hdata->nr_channels; tmp++) {
+ if (carr[tmp] == 0 || carr[tmp] > DMAC_MAX_BLK_SIZE)
+ return -EINVAL;
+
+ chip->dw->hdata->block_size[tmp] = carr[tmp];
+ }
+
+ ret = device_property_read_u32_array(dev, "snps,priority", carr,
+ chip->dw->hdata->nr_channels);
+ if (ret)
+ return ret;
+ /* Priority value must be programmed within [0:nr_channels-1] range */
+ for (tmp = 0; tmp < chip->dw->hdata->nr_channels; tmp++) {
+ if (carr[tmp] >= chip->dw->hdata->nr_channels)
+ return -EINVAL;
+
+ chip->dw->hdata->priority[tmp] = carr[tmp];
+ }
+
+ /* axi-max-burst-len is optional property */
+ ret = device_property_read_u32(dev, "snps,axi-max-burst-len", &tmp);
+ if (!ret) {
+ if (tmp > DWAXIDMAC_ARWLEN_MAX + 1)
+ return -EINVAL;
+ if (tmp < DWAXIDMAC_ARWLEN_MIN + 1)
+ return -EINVAL;
+
+ chip->dw->hdata->restrict_axi_burst_len = true;
+ chip->dw->hdata->axi_rw_burst_len = tmp - 1;
+ }
+
+ return 0;
+}
+
+static int dw_probe(struct platform_device *pdev)
+{
+ struct axi_dma_chip *chip;
+ struct resource *mem;
+ struct dw_axi_dma *dw;
+ struct dw_axi_dma_hcfg *hdata;
+ u32 i;
+ int ret;
+
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ dw = devm_kzalloc(&pdev->dev, sizeof(*dw), GFP_KERNEL);
+ if (!dw)
+ return -ENOMEM;
+
+ hdata = devm_kzalloc(&pdev->dev, sizeof(*hdata), GFP_KERNEL);
+ if (!hdata)
+ return -ENOMEM;
+
+ chip->dw = dw;
+ chip->dev = &pdev->dev;
+ chip->dw->hdata = hdata;
+
+ chip->irq = platform_get_irq(pdev, 0);
+ if (chip->irq < 0)
+ return chip->irq;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ chip->regs = devm_ioremap_resource(chip->dev, mem);
+ if (IS_ERR(chip->regs))
+ return PTR_ERR(chip->regs);
+
+ chip->core_clk = devm_clk_get(chip->dev, "core-clk");
+ if (IS_ERR(chip->core_clk))
+ return PTR_ERR(chip->core_clk);
+
+ chip->cfgr_clk = devm_clk_get(chip->dev, "cfgr-clk");
+ if (IS_ERR(chip->cfgr_clk))
+ return PTR_ERR(chip->cfgr_clk);
+
+ ret = parse_device_properties(chip);
+ if (ret)
+ return ret;
+
+ dw->chan = devm_kcalloc(chip->dev, hdata->nr_channels,
+ sizeof(*dw->chan), GFP_KERNEL);
+ if (!dw->chan)
+ return -ENOMEM;
+
+ ret = devm_request_irq(chip->dev, chip->irq, dw_axi_dma_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip);
+ if (ret)
+ return ret;
+
+ /* Lli address must be aligned to a 64-byte boundary */
+ dw->desc_pool = dmam_pool_create(KBUILD_MODNAME, chip->dev,
+ sizeof(struct axi_dma_desc), 64, 0);
+ if (!dw->desc_pool) {
+ dev_err(chip->dev, "No memory for descriptors dma pool\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&dw->dma.channels);
+ for (i = 0; i < hdata->nr_channels; i++) {
+ struct axi_dma_chan *chan = &dw->chan[i];
+
+ chan->chip = chip;
+ chan->id = i;
+ chan->chan_regs = chip->regs + COMMON_REG_LEN + i * CHAN_REG_LEN;
+ atomic_set(&chan->descs_allocated, 0);
+
+ chan->vc.desc_free = vchan_desc_put;
+ vchan_init(&chan->vc, &dw->dma);
+ }
+
+ /* Set capabilities */
+ dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask);
+
+ /* DMA capabilities */
+ dw->dma.chancnt = hdata->nr_channels;
+ dw->dma.src_addr_widths = AXI_DMA_BUSWIDTHS;
+ dw->dma.dst_addr_widths = AXI_DMA_BUSWIDTHS;
+ dw->dma.directions = BIT(DMA_MEM_TO_MEM);
+ dw->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
+
+ dw->dma.dev = chip->dev;
+ dw->dma.device_tx_status = dma_chan_tx_status;
+ dw->dma.device_issue_pending = dma_chan_issue_pending;
+ dw->dma.device_terminate_all = dma_chan_terminate_all;
+ dw->dma.device_pause = dma_chan_pause;
+ dw->dma.device_resume = dma_chan_resume;
+
+ dw->dma.device_alloc_chan_resources = dma_chan_alloc_chan_resources;
+ dw->dma.device_free_chan_resources = dma_chan_free_chan_resources;
+
+ dw->dma.device_prep_dma_memcpy = dma_chan_prep_dma_memcpy;
+
+ platform_set_drvdata(pdev, chip);
+
+ pm_runtime_enable(chip->dev);
+
+ /*
+ * We can't just call pm_runtime_get here instead of
+ * pm_runtime_get_noresume + axi_dma_resume because we need
+ * driver to work also without Runtime PM.
+ */
+ pm_runtime_get_noresume(chip->dev);
+ ret = axi_dma_resume(chip);
+ if (ret < 0)
+ goto err_pm_disable;
+
+ axi_dma_hw_init(chip);
+
+ pm_runtime_put(chip->dev);
+
+ ret = dma_async_device_register(&dw->dma);
+ if (ret)
+ goto err_pm_disable;
+
+ dev_info(chip->dev, "DesignWare AXI DMA Controller, %d channels\n",
+ dw->hdata->nr_channels);
+
+ return 0;
+
+err_pm_disable:
+ pm_runtime_disable(chip->dev);
+
+ return ret;
+}
+
+static int dw_remove(struct platform_device *pdev)
+{
+ struct axi_dma_chip *chip = platform_get_drvdata(pdev);
+ struct dw_axi_dma *dw = chip->dw;
+ struct axi_dma_chan *chan, *_chan;
+ u32 i;
+
+ /* Enable clk before accessing to registers */
+ clk_prepare_enable(chip->cfgr_clk);
+ clk_prepare_enable(chip->core_clk);
+ axi_dma_irq_disable(chip);
+ for (i = 0; i < dw->hdata->nr_channels; i++) {
+ axi_chan_disable(&chip->dw->chan[i]);
+ axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
+ }
+ axi_dma_disable(chip);
+
+ pm_runtime_disable(chip->dev);
+ axi_dma_suspend(chip);
+
+ devm_free_irq(chip->dev, chip->irq, chip);
+
+ list_for_each_entry_safe(chan, _chan, &dw->dma.channels,
+ vc.chan.device_node) {
+ list_del(&chan->vc.chan.device_node);
+ tasklet_kill(&chan->vc.task);
+ }
+
+ dma_async_device_unregister(&dw->dma);
+
+ return 0;
+}
+
+static const struct dev_pm_ops dw_axi_dma_pm_ops = {
+ SET_RUNTIME_PM_OPS(axi_dma_runtime_suspend, axi_dma_runtime_resume, NULL)
+};
+
+static const struct of_device_id dw_dma_of_id_table[] = {
+ { .compatible = "snps,axi-dma-1.01a" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
+
+static struct platform_driver dw_driver = {
+ .probe = dw_probe,
+ .remove = dw_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = of_match_ptr(dw_dma_of_id_table),
+ .pm = &dw_axi_dma_pm_ops,
+ },
+};
+module_platform_driver(dw_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Synopsys DesignWare AXI DMA Controller platform driver");
+MODULE_AUTHOR("Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>");
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
new file mode 100644
index 000000000000..f8888dc0b8dc
--- /dev/null
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0
+// (C) 2017-2018 Synopsys, Inc. (www.synopsys.com)
+
+/*
+ * Synopsys DesignWare AXI DMA Controller driver.
+ *
+ * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
+ */
+
+#ifndef _AXI_DMA_PLATFORM_H
+#define _AXI_DMA_PLATFORM_H
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/types.h>
+
+#include "../virt-dma.h"
+
+#define DMAC_MAX_CHANNELS 8
+#define DMAC_MAX_MASTERS 2
+#define DMAC_MAX_BLK_SIZE 0x200000
+
+struct dw_axi_dma_hcfg {
+ u32 nr_channels;
+ u32 nr_masters;
+ u32 m_data_width;
+ u32 block_size[DMAC_MAX_CHANNELS];
+ u32 priority[DMAC_MAX_CHANNELS];
+ /* maximum supported axi burst length */
+ u32 axi_rw_burst_len;
+ bool restrict_axi_burst_len;
+};
+
+struct axi_dma_chan {
+ struct axi_dma_chip *chip;
+ void __iomem *chan_regs;
+ u8 id;
+ atomic_t descs_allocated;
+
+ struct virt_dma_chan vc;
+
+ /* these other elements are all protected by vc.lock */
+ bool is_paused;
+};
+
+struct dw_axi_dma {
+ struct dma_device dma;
+ struct dw_axi_dma_hcfg *hdata;
+ struct dma_pool *desc_pool;
+
+ /* channels */
+ struct axi_dma_chan *chan;
+};
+
+struct axi_dma_chip {
+ struct device *dev;
+ int irq;
+ void __iomem *regs;
+ struct clk *core_clk;
+ struct clk *cfgr_clk;
+ struct dw_axi_dma *dw;
+};
+
+/* LLI == Linked List Item */
+struct __packed axi_dma_lli {
+ __le64 sar;
+ __le64 dar;
+ __le32 block_ts_lo;
+ __le32 block_ts_hi;
+ __le64 llp;
+ __le32 ctl_lo;
+ __le32 ctl_hi;
+ __le32 sstat;
+ __le32 dstat;
+ __le32 status_lo;
+ __le32 ststus_hi;
+ __le32 reserved_lo;
+ __le32 reserved_hi;
+};
+
+struct axi_dma_desc {
+ struct axi_dma_lli lli;
+
+ struct virt_dma_desc vd;
+ struct axi_dma_chan *chan;
+ struct list_head xfer_list;
+};
+
+static inline struct device *dchan2dev(struct dma_chan *dchan)
+{
+ return &dchan->dev->device;
+}
+
+static inline struct device *chan2dev(struct axi_dma_chan *chan)
+{
+ return &chan->vc.chan.dev->device;
+}
+
+static inline struct axi_dma_desc *vd_to_axi_desc(struct virt_dma_desc *vd)
+{
+ return container_of(vd, struct axi_dma_desc, vd);
+}
+
+static inline struct axi_dma_chan *vc_to_axi_dma_chan(struct virt_dma_chan *vc)
+{
+ return container_of(vc, struct axi_dma_chan, vc);
+}
+
+static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
+{
+ return vc_to_axi_dma_chan(to_virt_chan(dchan));
+}
+
+
+#define COMMON_REG_LEN 0x100
+#define CHAN_REG_LEN 0x100
+
+/* Common registers offset */
+#define DMAC_ID 0x000 /* R DMAC ID */
+#define DMAC_COMPVER 0x008 /* R DMAC Component Version */
+#define DMAC_CFG 0x010 /* R/W DMAC Configuration */
+#define DMAC_CHEN 0x018 /* R/W DMAC Channel Enable */
+#define DMAC_CHEN_L 0x018 /* R/W DMAC Channel Enable 00-31 */
+#define DMAC_CHEN_H 0x01C /* R/W DMAC Channel Enable 32-63 */
+#define DMAC_INTSTATUS 0x030 /* R DMAC Interrupt Status */
+#define DMAC_COMMON_INTCLEAR 0x038 /* W DMAC Interrupt Clear */
+#define DMAC_COMMON_INTSTATUS_ENA 0x040 /* R DMAC Interrupt Status Enable */
+#define DMAC_COMMON_INTSIGNAL_ENA 0x048 /* R/W DMAC Interrupt Signal Enable */
+#define DMAC_COMMON_INTSTATUS 0x050 /* R DMAC Interrupt Status */
+#define DMAC_RESET 0x058 /* R DMAC Reset Register1 */
+
+/* DMA channel registers offset */
+#define CH_SAR 0x000 /* R/W Chan Source Address */
+#define CH_DAR 0x008 /* R/W Chan Destination Address */
+#define CH_BLOCK_TS 0x010 /* R/W Chan Block Transfer Size */
+#define CH_CTL 0x018 /* R/W Chan Control */
+#define CH_CTL_L 0x018 /* R/W Chan Control 00-31 */
+#define CH_CTL_H 0x01C /* R/W Chan Control 32-63 */
+#define CH_CFG 0x020 /* R/W Chan Configuration */
+#define CH_CFG_L 0x020 /* R/W Chan Configuration 00-31 */
+#define CH_CFG_H 0x024 /* R/W Chan Configuration 32-63 */
+#define CH_LLP 0x028 /* R/W Chan Linked List Pointer */
+#define CH_STATUS 0x030 /* R Chan Status */
+#define CH_SWHSSRC 0x038 /* R/W Chan SW Handshake Source */
+#define CH_SWHSDST 0x040 /* R/W Chan SW Handshake Destination */
+#define CH_BLK_TFR_RESUMEREQ 0x048 /* W Chan Block Transfer Resume Req */
+#define CH_AXI_ID 0x050 /* R/W Chan AXI ID */
+#define CH_AXI_QOS 0x058 /* R/W Chan AXI QOS */
+#define CH_SSTAT 0x060 /* R Chan Source Status */
+#define CH_DSTAT 0x068 /* R Chan Destination Status */
+#define CH_SSTATAR 0x070 /* R/W Chan Source Status Fetch Addr */
+#define CH_DSTATAR 0x078 /* R/W Chan Destination Status Fetch Addr */
+#define CH_INTSTATUS_ENA 0x080 /* R/W Chan Interrupt Status Enable */
+#define CH_INTSTATUS 0x088 /* R/W Chan Interrupt Status */
+#define CH_INTSIGNAL_ENA 0x090 /* R/W Chan Interrupt Signal Enable */
+#define CH_INTCLEAR 0x098 /* W Chan Interrupt Clear */
+
+
+/* DMAC_CFG */
+#define DMAC_EN_POS 0
+#define DMAC_EN_MASK BIT(DMAC_EN_POS)
+
+#define INT_EN_POS 1
+#define INT_EN_MASK BIT(INT_EN_POS)
+
+#define DMAC_CHAN_EN_SHIFT 0
+#define DMAC_CHAN_EN_WE_SHIFT 8
+
+#define DMAC_CHAN_SUSP_SHIFT 16
+#define DMAC_CHAN_SUSP_WE_SHIFT 24
+
+/* CH_CTL_H */
+#define CH_CTL_H_ARLEN_EN BIT(6)
+#define CH_CTL_H_ARLEN_POS 7
+#define CH_CTL_H_AWLEN_EN BIT(15)
+#define CH_CTL_H_AWLEN_POS 16
+
+enum {
+ DWAXIDMAC_ARWLEN_1 = 0,
+ DWAXIDMAC_ARWLEN_2 = 1,
+ DWAXIDMAC_ARWLEN_4 = 3,
+ DWAXIDMAC_ARWLEN_8 = 7,
+ DWAXIDMAC_ARWLEN_16 = 15,
+ DWAXIDMAC_ARWLEN_32 = 31,
+ DWAXIDMAC_ARWLEN_64 = 63,
+ DWAXIDMAC_ARWLEN_128 = 127,
+ DWAXIDMAC_ARWLEN_256 = 255,
+ DWAXIDMAC_ARWLEN_MIN = DWAXIDMAC_ARWLEN_1,
+ DWAXIDMAC_ARWLEN_MAX = DWAXIDMAC_ARWLEN_256
+};
+
+#define CH_CTL_H_LLI_LAST BIT(30)
+#define CH_CTL_H_LLI_VALID BIT(31)
+
+/* CH_CTL_L */
+#define CH_CTL_L_LAST_WRITE_EN BIT(30)
+
+#define CH_CTL_L_DST_MSIZE_POS 18
+#define CH_CTL_L_SRC_MSIZE_POS 14
+
+enum {
+ DWAXIDMAC_BURST_TRANS_LEN_1 = 0,
+ DWAXIDMAC_BURST_TRANS_LEN_4,
+ DWAXIDMAC_BURST_TRANS_LEN_8,
+ DWAXIDMAC_BURST_TRANS_LEN_16,
+ DWAXIDMAC_BURST_TRANS_LEN_32,
+ DWAXIDMAC_BURST_TRANS_LEN_64,
+ DWAXIDMAC_BURST_TRANS_LEN_128,
+ DWAXIDMAC_BURST_TRANS_LEN_256,
+ DWAXIDMAC_BURST_TRANS_LEN_512,
+ DWAXIDMAC_BURST_TRANS_LEN_1024
+};
+
+#define CH_CTL_L_DST_WIDTH_POS 11
+#define CH_CTL_L_SRC_WIDTH_POS 8
+
+#define CH_CTL_L_DST_INC_POS 6
+#define CH_CTL_L_SRC_INC_POS 4
+enum {
+ DWAXIDMAC_CH_CTL_L_INC = 0,
+ DWAXIDMAC_CH_CTL_L_NOINC
+};
+
+#define CH_CTL_L_DST_MAST BIT(2)
+#define CH_CTL_L_SRC_MAST BIT(0)
+
+/* CH_CFG_H */
+#define CH_CFG_H_PRIORITY_POS 17
+#define CH_CFG_H_HS_SEL_DST_POS 4
+#define CH_CFG_H_HS_SEL_SRC_POS 3
+enum {
+ DWAXIDMAC_HS_SEL_HW = 0,
+ DWAXIDMAC_HS_SEL_SW
+};
+
+#define CH_CFG_H_TT_FC_POS 0
+enum {
+ DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC = 0,
+ DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC,
+ DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC,
+ DWAXIDMAC_TT_FC_PER_TO_PER_DMAC,
+ DWAXIDMAC_TT_FC_PER_TO_MEM_SRC,
+ DWAXIDMAC_TT_FC_PER_TO_PER_SRC,
+ DWAXIDMAC_TT_FC_MEM_TO_PER_DST,
+ DWAXIDMAC_TT_FC_PER_TO_PER_DST
+};
+
+/* CH_CFG_L */
+#define CH_CFG_L_DST_MULTBLK_TYPE_POS 2
+#define CH_CFG_L_SRC_MULTBLK_TYPE_POS 0
+enum {
+ DWAXIDMAC_MBLK_TYPE_CONTIGUOUS = 0,
+ DWAXIDMAC_MBLK_TYPE_RELOAD,
+ DWAXIDMAC_MBLK_TYPE_SHADOW_REG,
+ DWAXIDMAC_MBLK_TYPE_LL
+};
+
+/**
+ * DW AXI DMA channel interrupts
+ *
+ * @DWAXIDMAC_IRQ_NONE: Bitmask of no one interrupt
+ * @DWAXIDMAC_IRQ_BLOCK_TRF: Block transfer complete
+ * @DWAXIDMAC_IRQ_DMA_TRF: Dma transfer complete
+ * @DWAXIDMAC_IRQ_SRC_TRAN: Source transaction complete
+ * @DWAXIDMAC_IRQ_DST_TRAN: Destination transaction complete
+ * @DWAXIDMAC_IRQ_SRC_DEC_ERR: Source decode error
+ * @DWAXIDMAC_IRQ_DST_DEC_ERR: Destination decode error
+ * @DWAXIDMAC_IRQ_SRC_SLV_ERR: Source slave error
+ * @DWAXIDMAC_IRQ_DST_SLV_ERR: Destination slave error
+ * @DWAXIDMAC_IRQ_LLI_RD_DEC_ERR: LLI read decode error
+ * @DWAXIDMAC_IRQ_LLI_WR_DEC_ERR: LLI write decode error
+ * @DWAXIDMAC_IRQ_LLI_RD_SLV_ERR: LLI read slave error
+ * @DWAXIDMAC_IRQ_LLI_WR_SLV_ERR: LLI write slave error
+ * @DWAXIDMAC_IRQ_INVALID_ERR: LLI invalid error or Shadow register error
+ * @DWAXIDMAC_IRQ_MULTIBLKTYPE_ERR: Slave Interface Multiblock type error
+ * @DWAXIDMAC_IRQ_DEC_ERR: Slave Interface decode error
+ * @DWAXIDMAC_IRQ_WR2RO_ERR: Slave Interface write to read only error
+ * @DWAXIDMAC_IRQ_RD2RWO_ERR: Slave Interface read to write only error
+ * @DWAXIDMAC_IRQ_WRONCHEN_ERR: Slave Interface write to channel error
+ * @DWAXIDMAC_IRQ_SHADOWREG_ERR: Slave Interface shadow reg error
+ * @DWAXIDMAC_IRQ_WRONHOLD_ERR: Slave Interface hold error
+ * @DWAXIDMAC_IRQ_LOCK_CLEARED: Lock Cleared Status
+ * @DWAXIDMAC_IRQ_SRC_SUSPENDED: Source Suspended Status
+ * @DWAXIDMAC_IRQ_SUSPENDED: Channel Suspended Status
+ * @DWAXIDMAC_IRQ_DISABLED: Channel Disabled Status
+ * @DWAXIDMAC_IRQ_ABORTED: Channel Aborted Status
+ * @DWAXIDMAC_IRQ_ALL_ERR: Bitmask of all error interrupts
+ * @DWAXIDMAC_IRQ_ALL: Bitmask of all interrupts
+ */
+enum {
+ DWAXIDMAC_IRQ_NONE = 0,
+ DWAXIDMAC_IRQ_BLOCK_TRF = BIT(0),
+ DWAXIDMAC_IRQ_DMA_TRF = BIT(1),
+ DWAXIDMAC_IRQ_SRC_TRAN = BIT(3),
+ DWAXIDMAC_IRQ_DST_TRAN = BIT(4),
+ DWAXIDMAC_IRQ_SRC_DEC_ERR = BIT(5),
+ DWAXIDMAC_IRQ_DST_DEC_ERR = BIT(6),
+ DWAXIDMAC_IRQ_SRC_SLV_ERR = BIT(7),
+ DWAXIDMAC_IRQ_DST_SLV_ERR = BIT(8),
+ DWAXIDMAC_IRQ_LLI_RD_DEC_ERR = BIT(9),
+ DWAXIDMAC_IRQ_LLI_WR_DEC_ERR = BIT(10),
+ DWAXIDMAC_IRQ_LLI_RD_SLV_ERR = BIT(11),
+ DWAXIDMAC_IRQ_LLI_WR_SLV_ERR = BIT(12),
+ DWAXIDMAC_IRQ_INVALID_ERR = BIT(13),
+ DWAXIDMAC_IRQ_MULTIBLKTYPE_ERR = BIT(14),
+ DWAXIDMAC_IRQ_DEC_ERR = BIT(16),
+ DWAXIDMAC_IRQ_WR2RO_ERR = BIT(17),
+ DWAXIDMAC_IRQ_RD2RWO_ERR = BIT(18),
+ DWAXIDMAC_IRQ_WRONCHEN_ERR = BIT(19),
+ DWAXIDMAC_IRQ_SHADOWREG_ERR = BIT(20),
+ DWAXIDMAC_IRQ_WRONHOLD_ERR = BIT(21),
+ DWAXIDMAC_IRQ_LOCK_CLEARED = BIT(27),
+ DWAXIDMAC_IRQ_SRC_SUSPENDED = BIT(28),
+ DWAXIDMAC_IRQ_SUSPENDED = BIT(29),
+ DWAXIDMAC_IRQ_DISABLED = BIT(30),
+ DWAXIDMAC_IRQ_ABORTED = BIT(31),
+ DWAXIDMAC_IRQ_ALL_ERR = (GENMASK(21, 16) | GENMASK(14, 5)),
+ DWAXIDMAC_IRQ_ALL = GENMASK(31, 0)
+};
+
+enum {
+ DWAXIDMAC_TRANS_WIDTH_8 = 0,
+ DWAXIDMAC_TRANS_WIDTH_16,
+ DWAXIDMAC_TRANS_WIDTH_32,
+ DWAXIDMAC_TRANS_WIDTH_64,
+ DWAXIDMAC_TRANS_WIDTH_128,
+ DWAXIDMAC_TRANS_WIDTH_256,
+ DWAXIDMAC_TRANS_WIDTH_512,
+ DWAXIDMAC_TRANS_WIDTH_MAX = DWAXIDMAC_TRANS_WIDTH_512
+};
+
+#endif /* _AXI_DMA_PLATFORM_H */
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 948df1ab5f1a..85ea92fcea54 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -1876,6 +1876,11 @@ static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode)
if (memcpy_channels) {
m_ddev = devm_kzalloc(ecc->dev, sizeof(*m_ddev), GFP_KERNEL);
+ if (!m_ddev) {
+ dev_warn(ecc->dev, "memcpy is disabled due to OoM\n");
+ memcpy_channels = NULL;
+ goto ch_setup;
+ }
ecc->dma_memcpy = m_ddev;
dma_cap_zero(m_ddev->cap_mask);
@@ -1903,6 +1908,7 @@ static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode)
dev_info(ecc->dev, "memcpy is disabled\n");
}
+ch_setup:
for (i = 0; i < ecc->num_channels; i++) {
struct edma_chan *echan = &ecc->slave_chans[i];
echan->ch_num = EDMA_CTLR_CHAN(ecc->id, i);
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index e7db24c67030..ccd03c3cedfe 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -338,6 +338,7 @@ struct sdma_channel {
unsigned int chn_real_count;
struct tasklet_struct tasklet;
struct imx_dma_data data;
+ bool enabled;
};
#define IMX_DMA_SG_LOOP BIT(0)
@@ -596,7 +597,14 @@ static int sdma_config_ownership(struct sdma_channel *sdmac,
static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
{
+ unsigned long flags;
+ struct sdma_channel *sdmac = &sdma->channel[channel];
+
writel(BIT(channel), sdma->regs + SDMA_H_START);
+
+ spin_lock_irqsave(&sdmac->lock, flags);
+ sdmac->enabled = true;
+ spin_unlock_irqrestore(&sdmac->lock, flags);
}
/*
@@ -685,6 +693,14 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
struct sdma_buffer_descriptor *bd;
int error = 0;
enum dma_status old_status = sdmac->status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sdmac->lock, flags);
+ if (!sdmac->enabled) {
+ spin_unlock_irqrestore(&sdmac->lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&sdmac->lock, flags);
/*
* loop mode. Iterate over descriptors, re-setup them and
@@ -938,10 +954,15 @@ static int sdma_disable_channel(struct dma_chan *chan)
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
int channel = sdmac->channel;
+ unsigned long flags;
writel_relaxed(BIT(channel), sdma->regs + SDMA_H_STATSTOP);
sdmac->status = DMA_ERROR;
+ spin_lock_irqsave(&sdmac->lock, flags);
+ sdmac->enabled = false;
+ spin_unlock_irqrestore(&sdmac->lock, flags);
+
return 0;
}
diff --git a/drivers/dma/mediatek/Kconfig b/drivers/dma/mediatek/Kconfig
new file mode 100644
index 000000000000..27bac0bba09e
--- /dev/null
+++ b/drivers/dma/mediatek/Kconfig
@@ -0,0 +1,13 @@
+
+config MTK_HSDMA
+ tristate "MediaTek High-Speed DMA controller support"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ ---help---
+ Enable support for High-Speed DMA controller on MediaTek
+ SoCs.
+
+ This controller provides the channels which is dedicated to
+ memory-to-memory transfer to offload from CPU through ring-
+ based descriptor management.
diff --git a/drivers/dma/mediatek/Makefile b/drivers/dma/mediatek/Makefile
new file mode 100644
index 000000000000..6e778f842f01
--- /dev/null
+++ b/drivers/dma/mediatek/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o
diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c
new file mode 100644
index 000000000000..b7ec56ae02a6
--- /dev/null
+++ b/drivers/dma/mediatek/mtk-hsdma.c
@@ -0,0 +1,1056 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017-2018 MediaTek Inc.
+
+/*
+ * Driver for MediaTek High-Speed DMA Controller
+ *
+ * Author: Sean Wang <sean.wang@mediatek.com>
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/refcount.h>
+#include <linux/slab.h>
+
+#include "../virt-dma.h"
+
+#define MTK_HSDMA_USEC_POLL 20
+#define MTK_HSDMA_TIMEOUT_POLL 200000
+#define MTK_HSDMA_DMA_BUSWIDTHS BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)
+
+/* The default number of virtual channel */
+#define MTK_HSDMA_NR_VCHANS 3
+
+/* Only one physical channel supported */
+#define MTK_HSDMA_NR_MAX_PCHANS 1
+
+/* Macro for physical descriptor (PD) manipulation */
+/* The number of PD which must be 2 of power */
+#define MTK_DMA_SIZE 64
+#define MTK_HSDMA_NEXT_DESP_IDX(x, y) (((x) + 1) & ((y) - 1))
+#define MTK_HSDMA_LAST_DESP_IDX(x, y) (((x) - 1) & ((y) - 1))
+#define MTK_HSDMA_MAX_LEN 0x3f80
+#define MTK_HSDMA_ALIGN_SIZE 4
+#define MTK_HSDMA_PLEN_MASK 0x3fff
+#define MTK_HSDMA_DESC_PLEN(x) (((x) & MTK_HSDMA_PLEN_MASK) << 16)
+#define MTK_HSDMA_DESC_PLEN_GET(x) (((x) >> 16) & MTK_HSDMA_PLEN_MASK)
+
+/* Registers for underlying ring manipulation */
+#define MTK_HSDMA_TX_BASE 0x0
+#define MTK_HSDMA_TX_CNT 0x4
+#define MTK_HSDMA_TX_CPU 0x8
+#define MTK_HSDMA_TX_DMA 0xc
+#define MTK_HSDMA_RX_BASE 0x100
+#define MTK_HSDMA_RX_CNT 0x104
+#define MTK_HSDMA_RX_CPU 0x108
+#define MTK_HSDMA_RX_DMA 0x10c
+
+/* Registers for global setup */
+#define MTK_HSDMA_GLO 0x204
+#define MTK_HSDMA_GLO_MULTI_DMA BIT(10)
+#define MTK_HSDMA_TX_WB_DDONE BIT(6)
+#define MTK_HSDMA_BURST_64BYTES (0x2 << 4)
+#define MTK_HSDMA_GLO_RX_BUSY BIT(3)
+#define MTK_HSDMA_GLO_RX_DMA BIT(2)
+#define MTK_HSDMA_GLO_TX_BUSY BIT(1)
+#define MTK_HSDMA_GLO_TX_DMA BIT(0)
+#define MTK_HSDMA_GLO_DMA (MTK_HSDMA_GLO_TX_DMA | \
+ MTK_HSDMA_GLO_RX_DMA)
+#define MTK_HSDMA_GLO_BUSY (MTK_HSDMA_GLO_RX_BUSY | \
+ MTK_HSDMA_GLO_TX_BUSY)
+#define MTK_HSDMA_GLO_DEFAULT (MTK_HSDMA_GLO_TX_DMA | \
+ MTK_HSDMA_GLO_RX_DMA | \
+ MTK_HSDMA_TX_WB_DDONE | \
+ MTK_HSDMA_BURST_64BYTES | \
+ MTK_HSDMA_GLO_MULTI_DMA)
+
+/* Registers for reset */
+#define MTK_HSDMA_RESET 0x208
+#define MTK_HSDMA_RST_TX BIT(0)
+#define MTK_HSDMA_RST_RX BIT(16)
+
+/* Registers for interrupt control */
+#define MTK_HSDMA_DLYINT 0x20c
+#define MTK_HSDMA_RXDLY_INT_EN BIT(15)
+
+/* Interrupt fires when the pending number's more than the specified */
+#define MTK_HSDMA_RXMAX_PINT(x) (((x) & 0x7f) << 8)
+
+/* Interrupt fires when the pending time's more than the specified in 20 us */
+#define MTK_HSDMA_RXMAX_PTIME(x) ((x) & 0x7f)
+#define MTK_HSDMA_DLYINT_DEFAULT (MTK_HSDMA_RXDLY_INT_EN | \
+ MTK_HSDMA_RXMAX_PINT(20) | \
+ MTK_HSDMA_RXMAX_PTIME(20))
+#define MTK_HSDMA_INT_STATUS 0x220
+#define MTK_HSDMA_INT_ENABLE 0x228
+#define MTK_HSDMA_INT_RXDONE BIT(16)
+
+enum mtk_hsdma_vdesc_flag {
+ MTK_HSDMA_VDESC_FINISHED = 0x01,
+};
+
+#define IS_MTK_HSDMA_VDESC_FINISHED(x) ((x) == MTK_HSDMA_VDESC_FINISHED)
+
+/**
+ * struct mtk_hsdma_pdesc - This is the struct holding info describing physical
+ * descriptor (PD) and its placement must be kept at
+ * 4-bytes alignment in little endian order.
+ * @desc[1-4]: The control pad used to indicate hardware how to
+ * deal with the descriptor such as source and
+ * destination address and data length. The maximum
+ * data length each pdesc can handle is 0x3f80 bytes
+ */
+struct mtk_hsdma_pdesc {
+ __le32 desc1;
+ __le32 desc2;
+ __le32 desc3;
+ __le32 desc4;
+} __packed __aligned(4);
+
+/**
+ * struct mtk_hsdma_vdesc - This is the struct holding info describing virtual
+ * descriptor (VD)
+ * @vd: An instance for struct virt_dma_desc
+ * @len: The total data size device wants to move
+ * @residue: The remaining data size device will move
+ * @dest: The destination address device wants to move to
+ * @src: The source address device wants to move from
+ */
+struct mtk_hsdma_vdesc {
+ struct virt_dma_desc vd;
+ size_t len;
+ size_t residue;
+ dma_addr_t dest;
+ dma_addr_t src;
+};
+
+/**
+ * struct mtk_hsdma_cb - This is the struct holding extra info required for RX
+ * ring to know what relevant VD the the PD is being
+ * mapped to.
+ * @vd: Pointer to the relevant VD.
+ * @flag: Flag indicating what action should be taken when VD
+ * is completed.
+ */
+struct mtk_hsdma_cb {
+ struct virt_dma_desc *vd;
+ enum mtk_hsdma_vdesc_flag flag;
+};
+
+/**
+ * struct mtk_hsdma_ring - This struct holds info describing underlying ring
+ * space
+ * @txd: The descriptor TX ring which describes DMA source
+ * information
+ * @rxd: The descriptor RX ring which describes DMA
+ * destination information
+ * @cb: The extra information pointed at by RX ring
+ * @tphys: The physical addr of TX ring
+ * @rphys: The physical addr of RX ring
+ * @cur_tptr: Pointer to the next free descriptor used by the host
+ * @cur_rptr: Pointer to the last done descriptor by the device
+ */
+struct mtk_hsdma_ring {
+ struct mtk_hsdma_pdesc *txd;
+ struct mtk_hsdma_pdesc *rxd;
+ struct mtk_hsdma_cb *cb;
+ dma_addr_t tphys;
+ dma_addr_t rphys;
+ u16 cur_tptr;
+ u16 cur_rptr;
+};
+
+/**
+ * struct mtk_hsdma_pchan - This is the struct holding info describing physical
+ * channel (PC)
+ * @ring: An instance for the underlying ring
+ * @sz_ring: Total size allocated for the ring
+ * @nr_free: Total number of free rooms in the ring. It would
+ * be accessed and updated frequently between IRQ
+ * context and user context to reflect whether ring
+ * can accept requests from VD.
+ */
+struct mtk_hsdma_pchan {
+ struct mtk_hsdma_ring ring;
+ size_t sz_ring;
+ atomic_t nr_free;
+};
+
+/**
+ * struct mtk_hsdma_vchan - This is the struct holding info describing virtual
+ * channel (VC)
+ * @vc: An instance for struct virt_dma_chan
+ * @issue_completion: The wait for all issued descriptors completited
+ * @issue_synchronize: Bool indicating channel synchronization starts
+ * @desc_hw_processing: List those descriptors the hardware is processing,
+ * which is protected by vc.lock
+ */
+struct mtk_hsdma_vchan {
+ struct virt_dma_chan vc;
+ struct completion issue_completion;
+ bool issue_synchronize;
+ struct list_head desc_hw_processing;
+};
+
+/**
+ * struct mtk_hsdma_soc - This is the struct holding differences among SoCs
+ * @ddone: Bit mask for DDONE
+ * @ls0: Bit mask for LS0
+ */
+struct mtk_hsdma_soc {
+ __le32 ddone;
+ __le32 ls0;
+};
+
+/**
+ * struct mtk_hsdma_device - This is the struct holding info describing HSDMA
+ * device
+ * @ddev: An instance for struct dma_device
+ * @base: The mapped register I/O base
+ * @clk: The clock that device internal is using
+ * @irq: The IRQ that device are using
+ * @dma_requests: The number of VCs the device supports to
+ * @vc: The pointer to all available VCs
+ * @pc: The pointer to the underlying PC
+ * @pc_refcnt: Track how many VCs are using the PC
+ * @lock: Lock protect agaisting multiple VCs access PC
+ * @soc: The pointer to area holding differences among
+ * vaious platform
+ */
+struct mtk_hsdma_device {
+ struct dma_device ddev;
+ void __iomem *base;
+ struct clk *clk;
+ u32 irq;
+
+ u32 dma_requests;
+ struct mtk_hsdma_vchan *vc;
+ struct mtk_hsdma_pchan *pc;
+ refcount_t pc_refcnt;
+
+ /* Lock used to protect against multiple VCs access PC */
+ spinlock_t lock;
+
+ const struct mtk_hsdma_soc *soc;
+};
+
+static struct mtk_hsdma_device *to_hsdma_dev(struct dma_chan *chan)
+{
+ return container_of(chan->device, struct mtk_hsdma_device, ddev);
+}
+
+static inline struct mtk_hsdma_vchan *to_hsdma_vchan(struct dma_chan *chan)
+{
+ return container_of(chan, struct mtk_hsdma_vchan, vc.chan);
+}
+
+static struct mtk_hsdma_vdesc *to_hsdma_vdesc(struct virt_dma_desc *vd)
+{
+ return container_of(vd, struct mtk_hsdma_vdesc, vd);
+}
+
+static struct device *hsdma2dev(struct mtk_hsdma_device *hsdma)
+{
+ return hsdma->ddev.dev;
+}
+
+static u32 mtk_dma_read(struct mtk_hsdma_device *hsdma, u32 reg)
+{
+ return readl(hsdma->base + reg);
+}
+
+static void mtk_dma_write(struct mtk_hsdma_device *hsdma, u32 reg, u32 val)
+{
+ writel(val, hsdma->base + reg);
+}
+
+static void mtk_dma_rmw(struct mtk_hsdma_device *hsdma, u32 reg,
+ u32 mask, u32 set)
+{
+ u32 val;
+
+ val = mtk_dma_read(hsdma, reg);
+ val &= ~mask;
+ val |= set;
+ mtk_dma_write(hsdma, reg, val);
+}
+
+static void mtk_dma_set(struct mtk_hsdma_device *hsdma, u32 reg, u32 val)
+{
+ mtk_dma_rmw(hsdma, reg, 0, val);
+}
+
+static void mtk_dma_clr(struct mtk_hsdma_device *hsdma, u32 reg, u32 val)
+{
+ mtk_dma_rmw(hsdma, reg, val, 0);
+}
+
+static void mtk_hsdma_vdesc_free(struct virt_dma_desc *vd)
+{
+ kfree(container_of(vd, struct mtk_hsdma_vdesc, vd));
+}
+
+static int mtk_hsdma_busy_wait(struct mtk_hsdma_device *hsdma)
+{
+ u32 status = 0;
+
+ return readl_poll_timeout(hsdma->base + MTK_HSDMA_GLO, status,
+ !(status & MTK_HSDMA_GLO_BUSY),
+ MTK_HSDMA_USEC_POLL,
+ MTK_HSDMA_TIMEOUT_POLL);
+}
+
+static int mtk_hsdma_alloc_pchan(struct mtk_hsdma_device *hsdma,
+ struct mtk_hsdma_pchan *pc)
+{
+ struct mtk_hsdma_ring *ring = &pc->ring;
+ int err;
+
+ memset(pc, 0, sizeof(*pc));
+
+ /*
+ * Allocate ring space where [0 ... MTK_DMA_SIZE - 1] is for TX ring
+ * and [MTK_DMA_SIZE ... 2 * MTK_DMA_SIZE - 1] is for RX ring.
+ */
+ pc->sz_ring = 2 * MTK_DMA_SIZE * sizeof(*ring->txd);
+ ring->txd = dma_zalloc_coherent(hsdma2dev(hsdma), pc->sz_ring,
+ &ring->tphys, GFP_NOWAIT);
+ if (!ring->txd)
+ return -ENOMEM;
+
+ ring->rxd = &ring->txd[MTK_DMA_SIZE];
+ ring->rphys = ring->tphys + MTK_DMA_SIZE * sizeof(*ring->txd);
+ ring->cur_tptr = 0;
+ ring->cur_rptr = MTK_DMA_SIZE - 1;
+
+ ring->cb = kcalloc(MTK_DMA_SIZE, sizeof(*ring->cb), GFP_NOWAIT);
+ if (!ring->cb) {
+ err = -ENOMEM;
+ goto err_free_dma;
+ }
+
+ atomic_set(&pc->nr_free, MTK_DMA_SIZE - 1);
+
+ /* Disable HSDMA and wait for the completion */
+ mtk_dma_clr(hsdma, MTK_HSDMA_GLO, MTK_HSDMA_GLO_DMA);
+ err = mtk_hsdma_busy_wait(hsdma);
+ if (err)
+ goto err_free_cb;
+
+ /* Reset */
+ mtk_dma_set(hsdma, MTK_HSDMA_RESET,
+ MTK_HSDMA_RST_TX | MTK_HSDMA_RST_RX);
+ mtk_dma_clr(hsdma, MTK_HSDMA_RESET,
+ MTK_HSDMA_RST_TX | MTK_HSDMA_RST_RX);
+
+ /* Setup HSDMA initial pointer in the ring */
+ mtk_dma_write(hsdma, MTK_HSDMA_TX_BASE, ring->tphys);
+ mtk_dma_write(hsdma, MTK_HSDMA_TX_CNT, MTK_DMA_SIZE);
+ mtk_dma_write(hsdma, MTK_HSDMA_TX_CPU, ring->cur_tptr);
+ mtk_dma_write(hsdma, MTK_HSDMA_TX_DMA, 0);
+ mtk_dma_write(hsdma, MTK_HSDMA_RX_BASE, ring->rphys);
+ mtk_dma_write(hsdma, MTK_HSDMA_RX_CNT, MTK_DMA_SIZE);
+ mtk_dma_write(hsdma, MTK_HSDMA_RX_CPU, ring->cur_rptr);
+ mtk_dma_write(hsdma, MTK_HSDMA_RX_DMA, 0);
+
+ /* Enable HSDMA */
+ mtk_dma_set(hsdma, MTK_HSDMA_GLO, MTK_HSDMA_GLO_DMA);
+
+ /* Setup delayed interrupt */
+ mtk_dma_write(hsdma, MTK_HSDMA_DLYINT, MTK_HSDMA_DLYINT_DEFAULT);
+
+ /* Enable interrupt */
+ mtk_dma_set(hsdma, MTK_HSDMA_INT_ENABLE, MTK_HSDMA_INT_RXDONE);
+
+ return 0;
+
+err_free_cb:
+ kfree(ring->cb);
+
+err_free_dma:
+ dma_free_coherent(hsdma2dev(hsdma),
+ pc->sz_ring, ring->txd, ring->tphys);
+ return err;
+}
+
+static void mtk_hsdma_free_pchan(struct mtk_hsdma_device *hsdma,
+ struct mtk_hsdma_pchan *pc)
+{
+ struct mtk_hsdma_ring *ring = &pc->ring;
+
+ /* Disable HSDMA and then wait for the completion */
+ mtk_dma_clr(hsdma, MTK_HSDMA_GLO, MTK_HSDMA_GLO_DMA);
+ mtk_hsdma_busy_wait(hsdma);
+
+ /* Reset pointer in the ring */
+ mtk_dma_clr(hsdma, MTK_HSDMA_INT_ENABLE, MTK_HSDMA_INT_RXDONE);
+ mtk_dma_write(hsdma, MTK_HSDMA_TX_BASE, 0);
+ mtk_dma_write(hsdma, MTK_HSDMA_TX_CNT, 0);
+ mtk_dma_write(hsdma, MTK_HSDMA_TX_CPU, 0);
+ mtk_dma_write(hsdma, MTK_HSDMA_RX_BASE, 0);
+ mtk_dma_write(hsdma, MTK_HSDMA_RX_CNT, 0);
+ mtk_dma_write(hsdma, MTK_HSDMA_RX_CPU, MTK_DMA_SIZE - 1);
+
+ kfree(ring->cb);
+
+ dma_free_coherent(hsdma2dev(hsdma),
+ pc->sz_ring, ring->txd, ring->tphys);
+}
+
+static int mtk_hsdma_issue_pending_vdesc(struct mtk_hsdma_device *hsdma,
+ struct mtk_hsdma_pchan *pc,
+ struct mtk_hsdma_vdesc *hvd)
+{
+ struct mtk_hsdma_ring *ring = &pc->ring;
+ struct mtk_hsdma_pdesc *txd, *rxd;
+ u16 reserved, prev, tlen, num_sgs;
+ unsigned long flags;
+
+ /* Protect against PC is accessed by multiple VCs simultaneously */
+ spin_lock_irqsave(&hsdma->lock, flags);
+
+ /*
+ * Reserve rooms, where pc->nr_free is used to track how many free
+ * rooms in the ring being updated in user and IRQ context.
+ */
+ num_sgs = DIV_ROUND_UP(hvd->len, MTK_HSDMA_MAX_LEN);
+ reserved = min_t(u16, num_sgs, atomic_read(&pc->nr_free));
+
+ if (!reserved) {
+ spin_unlock_irqrestore(&hsdma->lock, flags);
+ return -ENOSPC;
+ }
+
+ atomic_sub(reserved, &pc->nr_free);
+
+ while (reserved--) {
+ /* Limit size by PD capability for valid data moving */
+ tlen = (hvd->len > MTK_HSDMA_MAX_LEN) ?
+ MTK_HSDMA_MAX_LEN : hvd->len;
+
+ /*
+ * Setup PDs using the remaining VD info mapped on those
+ * reserved rooms. And since RXD is shared memory between the
+ * host and the device allocated by dma_alloc_coherent call,
+ * the helper macro WRITE_ONCE can ensure the data written to
+ * RAM would really happens.
+ */
+ txd = &ring->txd[ring->cur_tptr];
+ WRITE_ONCE(txd->desc1, hvd->src);
+ WRITE_ONCE(txd->desc2,
+ hsdma->soc->ls0 | MTK_HSDMA_DESC_PLEN(tlen));
+
+ rxd = &ring->rxd[ring->cur_tptr];
+ WRITE_ONCE(rxd->desc1, hvd->dest);
+ WRITE_ONCE(rxd->desc2, MTK_HSDMA_DESC_PLEN(tlen));
+
+ /* Associate VD, the PD belonged to */
+ ring->cb[ring->cur_tptr].vd = &hvd->vd;
+
+ /* Move forward the pointer of TX ring */
+ ring->cur_tptr = MTK_HSDMA_NEXT_DESP_IDX(ring->cur_tptr,
+ MTK_DMA_SIZE);
+
+ /* Update VD with remaining data */
+ hvd->src += tlen;
+ hvd->dest += tlen;
+ hvd->len -= tlen;
+ }
+
+ /*
+ * Tagging flag for the last PD for VD will be responsible for
+ * completing VD.
+ */
+ if (!hvd->len) {
+ prev = MTK_HSDMA_LAST_DESP_IDX(ring->cur_tptr, MTK_DMA_SIZE);
+ ring->cb[prev].flag = MTK_HSDMA_VDESC_FINISHED;
+ }
+
+ /* Ensure all changes indeed done before we're going on */
+ wmb();
+
+ /*
+ * Updating into hardware the pointer of TX ring lets HSDMA to take
+ * action for those pending PDs.
+ */
+ mtk_dma_write(hsdma, MTK_HSDMA_TX_CPU, ring->cur_tptr);
+
+ spin_unlock_irqrestore(&hsdma->lock, flags);
+
+ return 0;
+}
+
+static void mtk_hsdma_issue_vchan_pending(struct mtk_hsdma_device *hsdma,
+ struct mtk_hsdma_vchan *hvc)
+{
+ struct virt_dma_desc *vd, *vd2;
+ int err;
+
+ lockdep_assert_held(&hvc->vc.lock);
+
+ list_for_each_entry_safe(vd, vd2, &hvc->vc.desc_issued, node) {
+ struct mtk_hsdma_vdesc *hvd;
+
+ hvd = to_hsdma_vdesc(vd);
+
+ /* Map VD into PC and all VCs shares a single PC */
+ err = mtk_hsdma_issue_pending_vdesc(hsdma, hsdma->pc, hvd);
+
+ /*
+ * Move VD from desc_issued to desc_hw_processing when entire
+ * VD is fit into available PDs. Otherwise, the uncompleted
+ * VDs would stay in list desc_issued and then restart the
+ * processing as soon as possible once underlying ring space
+ * got freed.
+ */
+ if (err == -ENOSPC || hvd->len > 0)
+ break;
+
+ /*
+ * The extra list desc_hw_processing is used because
+ * hardware can't provide sufficient information allowing us
+ * to know what VDs are still working on the underlying ring.
+ * Through the additional list, it can help us to implement
+ * terminate_all, residue calculation and such thing needed
+ * to know detail descriptor status on the hardware.
+ */
+ list_move_tail(&vd->node, &hvc->desc_hw_processing);
+ }
+}
+
+static void mtk_hsdma_free_rooms_in_ring(struct mtk_hsdma_device *hsdma)
+{
+ struct mtk_hsdma_vchan *hvc;
+ struct mtk_hsdma_pdesc *rxd;
+ struct mtk_hsdma_vdesc *hvd;
+ struct mtk_hsdma_pchan *pc;
+ struct mtk_hsdma_cb *cb;
+ int i = MTK_DMA_SIZE;
+ __le32 desc2;
+ u32 status;
+ u16 next;
+
+ /* Read IRQ status */
+ status = mtk_dma_read(hsdma, MTK_HSDMA_INT_STATUS);
+ if (unlikely(!(status & MTK_HSDMA_INT_RXDONE)))
+ goto rx_done;
+
+ pc = hsdma->pc;
+
+ /*
+ * Using a fail-safe loop with iterations of up to MTK_DMA_SIZE to
+ * reclaim these finished descriptors: The most number of PDs the ISR
+ * can handle at one time shouldn't be more than MTK_DMA_SIZE so we
+ * take it as limited count instead of just using a dangerous infinite
+ * poll.
+ */
+ while (i--) {
+ next = MTK_HSDMA_NEXT_DESP_IDX(pc->ring.cur_rptr,
+ MTK_DMA_SIZE);
+ rxd = &pc->ring.rxd[next];
+
+ /*
+ * If MTK_HSDMA_DESC_DDONE is no specified, that means data
+ * moving for the PD is still under going.
+ */
+ desc2 = READ_ONCE(rxd->desc2);
+ if (!(desc2 & hsdma->soc->ddone))
+ break;
+
+ cb = &pc->ring.cb[next];
+ if (unlikely(!cb->vd)) {
+ dev_err(hsdma2dev(hsdma), "cb->vd cannot be null\n");
+ break;
+ }
+
+ /* Update residue of VD the associated PD belonged to */
+ hvd = to_hsdma_vdesc(cb->vd);
+ hvd->residue -= MTK_HSDMA_DESC_PLEN_GET(rxd->desc2);
+
+ /* Complete VD until the relevant last PD is finished */
+ if (IS_MTK_HSDMA_VDESC_FINISHED(cb->flag)) {
+ hvc = to_hsdma_vchan(cb->vd->tx.chan);
+
+ spin_lock(&hvc->vc.lock);
+
+ /* Remove VD from list desc_hw_processing */
+ list_del(&cb->vd->node);
+
+ /* Add VD into list desc_completed */
+ vchan_cookie_complete(cb->vd);
+
+ if (hvc->issue_synchronize &&
+ list_empty(&hvc->desc_hw_processing)) {
+ complete(&hvc->issue_completion);
+ hvc->issue_synchronize = false;
+ }
+ spin_unlock(&hvc->vc.lock);
+
+ cb->flag = 0;
+ }
+
+ cb->vd = 0;
+
+ /*
+ * Recycle the RXD with the helper WRITE_ONCE that can ensure
+ * data written into RAM would really happens.
+ */
+ WRITE_ONCE(rxd->desc1, 0);
+ WRITE_ONCE(rxd->desc2, 0);
+ pc->ring.cur_rptr = next;
+
+ /* Release rooms */
+ atomic_inc(&pc->nr_free);
+ }
+
+ /* Ensure all changes indeed done before we're going on */
+ wmb();
+
+ /* Update CPU pointer for those completed PDs */
+ mtk_dma_write(hsdma, MTK_HSDMA_RX_CPU, pc->ring.cur_rptr);
+
+ /*
+ * Acking the pending IRQ allows hardware no longer to keep the used
+ * IRQ line in certain trigger state when software has completed all
+ * the finished physical descriptors.
+ */
+ if (atomic_read(&pc->nr_free) >= MTK_DMA_SIZE - 1)
+ mtk_dma_write(hsdma, MTK_HSDMA_INT_STATUS, status);
+
+ /* ASAP handles pending VDs in all VCs after freeing some rooms */
+ for (i = 0; i < hsdma->dma_requests; i++) {
+ hvc = &hsdma->vc[i];
+ spin_lock(&hvc->vc.lock);
+ mtk_hsdma_issue_vchan_pending(hsdma, hvc);
+ spin_unlock(&hvc->vc.lock);
+ }
+
+rx_done:
+ /* All completed PDs are cleaned up, so enable interrupt again */
+ mtk_dma_set(hsdma, MTK_HSDMA_INT_ENABLE, MTK_HSDMA_INT_RXDONE);
+}
+
+static irqreturn_t mtk_hsdma_irq(int irq, void *devid)
+{
+ struct mtk_hsdma_device *hsdma = devid;
+
+ /*
+ * Disable interrupt until all completed PDs are cleaned up in
+ * mtk_hsdma_free_rooms call.
+ */
+ mtk_dma_clr(hsdma, MTK_HSDMA_INT_ENABLE, MTK_HSDMA_INT_RXDONE);
+
+ mtk_hsdma_free_rooms_in_ring(hsdma);
+
+ return IRQ_HANDLED;
+}
+
+static struct virt_dma_desc *mtk_hsdma_find_active_desc(struct dma_chan *c,
+ dma_cookie_t cookie)
+{
+ struct mtk_hsdma_vchan *hvc = to_hsdma_vchan(c);
+ struct virt_dma_desc *vd;
+
+ list_for_each_entry(vd, &hvc->desc_hw_processing, node)
+ if (vd->tx.cookie == cookie)
+ return vd;
+
+ list_for_each_entry(vd, &hvc->vc.desc_issued, node)
+ if (vd->tx.cookie == cookie)
+ return vd;
+
+ return NULL;
+}
+
+static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c,
+ dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct mtk_hsdma_vchan *hvc = to_hsdma_vchan(c);
+ struct mtk_hsdma_vdesc *hvd;
+ struct virt_dma_desc *vd;
+ enum dma_status ret;
+ unsigned long flags;
+ size_t bytes = 0;
+
+ ret = dma_cookie_status(c, cookie, txstate);
+ if (ret == DMA_COMPLETE || !txstate)
+ return ret;
+
+ spin_lock_irqsave(&hvc->vc.lock, flags);
+ vd = mtk_hsdma_find_active_desc(c, cookie);
+ spin_unlock_irqrestore(&hvc->vc.lock, flags);
+
+ if (vd) {
+ hvd = to_hsdma_vdesc(vd);
+ bytes = hvd->residue;
+ }
+
+ dma_set_residue(txstate, bytes);
+
+ return ret;
+}
+
+static void mtk_hsdma_issue_pending(struct dma_chan *c)
+{
+ struct mtk_hsdma_device *hsdma = to_hsdma_dev(c);
+ struct mtk_hsdma_vchan *hvc = to_hsdma_vchan(c);
+ unsigned long flags;
+
+ spin_lock_irqsave(&hvc->vc.lock, flags);
+
+ if (vchan_issue_pending(&hvc->vc))
+ mtk_hsdma_issue_vchan_pending(hsdma, hvc);
+
+ spin_unlock_irqrestore(&hvc->vc.lock, flags);
+}
+
+static struct dma_async_tx_descriptor *
+mtk_hsdma_prep_dma_memcpy(struct dma_chan *c, dma_addr_t dest,
+ dma_addr_t src, size_t len, unsigned long flags)
+{
+ struct mtk_hsdma_vdesc *hvd;
+
+ hvd = kzalloc(sizeof(*hvd), GFP_NOWAIT);
+ if (!hvd)
+ return NULL;
+
+ hvd->len = len;
+ hvd->residue = len;
+ hvd->src = src;
+ hvd->dest = dest;
+
+ return vchan_tx_prep(to_virt_chan(c), &hvd->vd, flags);
+}
+
+static int mtk_hsdma_free_inactive_desc(struct dma_chan *c)
+{
+ struct virt_dma_chan *vc = to_virt_chan(c);
+ unsigned long flags;
+ LIST_HEAD(head);
+
+ spin_lock_irqsave(&vc->lock, flags);
+ list_splice_tail_init(&vc->desc_allocated, &head);
+ list_splice_tail_init(&vc->desc_submitted, &head);
+ list_splice_tail_init(&vc->desc_issued, &head);
+ spin_unlock_irqrestore(&vc->lock, flags);
+
+ /* At the point, we don't expect users put descriptor into VC again */
+ vchan_dma_desc_free_list(vc, &head);
+
+ return 0;
+}
+
+static void mtk_hsdma_free_active_desc(struct dma_chan *c)
+{
+ struct mtk_hsdma_vchan *hvc = to_hsdma_vchan(c);
+ bool sync_needed = false;
+
+ /*
+ * Once issue_synchronize is being set, which means once the hardware
+ * consumes all descriptors for the channel in the ring, the
+ * synchronization must be be notified immediately it is completed.
+ */
+ spin_lock(&hvc->vc.lock);
+ if (!list_empty(&hvc->desc_hw_processing)) {
+ hvc->issue_synchronize = true;
+ sync_needed = true;
+ }
+ spin_unlock(&hvc->vc.lock);
+
+ if (sync_needed)
+ wait_for_completion(&hvc->issue_completion);
+ /*
+ * At the point, we expect that all remaining descriptors in the ring
+ * for the channel should be all processing done.
+ */
+ WARN_ONCE(!list_empty(&hvc->desc_hw_processing),
+ "Desc pending still in list desc_hw_processing\n");
+
+ /* Free all descriptors in list desc_completed */
+ vchan_synchronize(&hvc->vc);
+
+ WARN_ONCE(!list_empty(&hvc->vc.desc_completed),
+ "Desc pending still in list desc_completed\n");
+}
+
+static int mtk_hsdma_terminate_all(struct dma_chan *c)
+{
+ /*
+ * Free pending descriptors not processed yet by hardware that have
+ * previously been submitted to the channel.
+ */
+ mtk_hsdma_free_inactive_desc(c);
+
+ /*
+ * However, the DMA engine doesn't provide any way to stop these
+ * descriptors being processed currently by hardware. The only way is
+ * to just waiting until these descriptors are all processed completely
+ * through mtk_hsdma_free_active_desc call.
+ */
+ mtk_hsdma_free_active_desc(c);
+
+ return 0;
+}
+
+static int mtk_hsdma_alloc_chan_resources(struct dma_chan *c)
+{
+ struct mtk_hsdma_device *hsdma = to_hsdma_dev(c);
+ int err;
+
+ /*
+ * Since HSDMA has only one PC, the resource for PC is being allocated
+ * when the first VC is being created and the other VCs would run on
+ * the same PC.
+ */
+ if (!refcount_read(&hsdma->pc_refcnt)) {
+ err = mtk_hsdma_alloc_pchan(hsdma, hsdma->pc);
+ if (err)
+ return err;
+ /*
+ * refcount_inc would complain increment on 0; use-after-free.
+ * Thus, we need to explicitly set it as 1 initially.
+ */
+ refcount_set(&hsdma->pc_refcnt, 1);
+ } else {
+ refcount_inc(&hsdma->pc_refcnt);
+ }
+
+ return 0;
+}
+
+static void mtk_hsdma_free_chan_resources(struct dma_chan *c)
+{
+ struct mtk_hsdma_device *hsdma = to_hsdma_dev(c);
+
+ /* Free all descriptors in all lists on the VC */
+ mtk_hsdma_terminate_all(c);
+
+ /* The resource for PC is not freed until all the VCs are destroyed */
+ if (!refcount_dec_and_test(&hsdma->pc_refcnt))
+ return;
+
+ mtk_hsdma_free_pchan(hsdma, hsdma->pc);
+}
+
+static int mtk_hsdma_hw_init(struct mtk_hsdma_device *hsdma)
+{
+ int err;
+
+ pm_runtime_enable(hsdma2dev(hsdma));
+ pm_runtime_get_sync(hsdma2dev(hsdma));
+
+ err = clk_prepare_enable(hsdma->clk);
+ if (err)
+ return err;
+
+ mtk_dma_write(hsdma, MTK_HSDMA_INT_ENABLE, 0);
+ mtk_dma_write(hsdma, MTK_HSDMA_GLO, MTK_HSDMA_GLO_DEFAULT);
+
+ return 0;
+}
+
+static int mtk_hsdma_hw_deinit(struct mtk_hsdma_device *hsdma)
+{
+ mtk_dma_write(hsdma, MTK_HSDMA_GLO, 0);
+
+ clk_disable_unprepare(hsdma->clk);
+
+ pm_runtime_put_sync(hsdma2dev(hsdma));
+ pm_runtime_disable(hsdma2dev(hsdma));
+
+ return 0;
+}
+
+static const struct mtk_hsdma_soc mt7623_soc = {
+ .ddone = BIT(31),
+ .ls0 = BIT(30),
+};
+
+static const struct mtk_hsdma_soc mt7622_soc = {
+ .ddone = BIT(15),
+ .ls0 = BIT(14),
+};
+
+static const struct of_device_id mtk_hsdma_match[] = {
+ { .compatible = "mediatek,mt7623-hsdma", .data = &mt7623_soc},
+ { .compatible = "mediatek,mt7622-hsdma", .data = &mt7622_soc},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mtk_hsdma_match);
+
+static int mtk_hsdma_probe(struct platform_device *pdev)
+{
+ struct mtk_hsdma_device *hsdma;
+ struct mtk_hsdma_vchan *vc;
+ struct dma_device *dd;
+ struct resource *res;
+ int i, err;
+
+ hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL);
+ if (!hsdma)
+ return -ENOMEM;
+
+ dd = &hsdma->ddev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ hsdma->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hsdma->base))
+ return PTR_ERR(hsdma->base);
+
+ hsdma->soc = of_device_get_match_data(&pdev->dev);
+ if (!hsdma->soc) {
+ dev_err(&pdev->dev, "No device match found\n");
+ return -ENODEV;
+ }
+
+ hsdma->clk = devm_clk_get(&pdev->dev, "hsdma");
+ if (IS_ERR(hsdma->clk)) {
+ dev_err(&pdev->dev, "No clock for %s\n",
+ dev_name(&pdev->dev));
+ return PTR_ERR(hsdma->clk);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "No irq resource for %s\n",
+ dev_name(&pdev->dev));
+ return -EINVAL;
+ }
+ hsdma->irq = res->start;
+
+ refcount_set(&hsdma->pc_refcnt, 0);
+ spin_lock_init(&hsdma->lock);
+
+ dma_cap_set(DMA_MEMCPY, dd->cap_mask);
+
+ dd->copy_align = MTK_HSDMA_ALIGN_SIZE;
+ dd->device_alloc_chan_resources = mtk_hsdma_alloc_chan_resources;
+ dd->device_free_chan_resources = mtk_hsdma_free_chan_resources;
+ dd->device_tx_status = mtk_hsdma_tx_status;
+ dd->device_issue_pending = mtk_hsdma_issue_pending;
+ dd->device_prep_dma_memcpy = mtk_hsdma_prep_dma_memcpy;
+ dd->device_terminate_all = mtk_hsdma_terminate_all;
+ dd->src_addr_widths = MTK_HSDMA_DMA_BUSWIDTHS;
+ dd->dst_addr_widths = MTK_HSDMA_DMA_BUSWIDTHS;
+ dd->directions = BIT(DMA_MEM_TO_MEM);
+ dd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+ dd->dev = &pdev->dev;
+ INIT_LIST_HEAD(&dd->channels);
+
+ hsdma->dma_requests = MTK_HSDMA_NR_VCHANS;
+ if (pdev->dev.of_node && of_property_read_u32(pdev->dev.of_node,
+ "dma-requests",
+ &hsdma->dma_requests)) {
+ dev_info(&pdev->dev,
+ "Using %u as missing dma-requests property\n",
+ MTK_HSDMA_NR_VCHANS);
+ }
+
+ hsdma->pc = devm_kcalloc(&pdev->dev, MTK_HSDMA_NR_MAX_PCHANS,
+ sizeof(*hsdma->pc), GFP_KERNEL);
+ if (!hsdma->pc)
+ return -ENOMEM;
+
+ hsdma->vc = devm_kcalloc(&pdev->dev, hsdma->dma_requests,
+ sizeof(*hsdma->vc), GFP_KERNEL);
+ if (!hsdma->vc)
+ return -ENOMEM;
+
+ for (i = 0; i < hsdma->dma_requests; i++) {
+ vc = &hsdma->vc[i];
+ vc->vc.desc_free = mtk_hsdma_vdesc_free;
+ vchan_init(&vc->vc, dd);
+ init_completion(&vc->issue_completion);
+ INIT_LIST_HEAD(&vc->desc_hw_processing);
+ }
+
+ err = dma_async_device_register(dd);
+ if (err)
+ return err;
+
+ err = of_dma_controller_register(pdev->dev.of_node,
+ of_dma_xlate_by_chan_id, hsdma);
+ if (err) {
+ dev_err(&pdev->dev,
+ "MediaTek HSDMA OF registration failed %d\n", err);
+ goto err_unregister;
+ }
+
+ mtk_hsdma_hw_init(hsdma);
+
+ err = devm_request_irq(&pdev->dev, hsdma->irq,
+ mtk_hsdma_irq, 0,
+ dev_name(&pdev->dev), hsdma);
+ if (err) {
+ dev_err(&pdev->dev,
+ "request_irq failed with err %d\n", err);
+ goto err_unregister;
+ }
+
+ platform_set_drvdata(pdev, hsdma);
+
+ dev_info(&pdev->dev, "MediaTek HSDMA driver registered\n");
+
+ return 0;
+
+err_unregister:
+ dma_async_device_unregister(dd);
+
+ return err;
+}
+
+static int mtk_hsdma_remove(struct platform_device *pdev)
+{
+ struct mtk_hsdma_device *hsdma = platform_get_drvdata(pdev);
+ struct mtk_hsdma_vchan *vc;
+ int i;
+
+ /* Kill VC task */
+ for (i = 0; i < hsdma->dma_requests; i++) {
+ vc = &hsdma->vc[i];
+
+ list_del(&vc->vc.chan.device_node);
+ tasklet_kill(&vc->vc.task);
+ }
+
+ /* Disable DMA interrupt */
+ mtk_dma_write(hsdma, MTK_HSDMA_INT_ENABLE, 0);
+
+ /* Waits for any pending IRQ handlers to complete */
+ synchronize_irq(hsdma->irq);
+
+ /* Disable hardware */
+ mtk_hsdma_hw_deinit(hsdma);
+
+ dma_async_device_unregister(&hsdma->ddev);
+ of_dma_controller_free(pdev->dev.of_node);
+
+ return 0;
+}
+
+static struct platform_driver mtk_hsdma_driver = {
+ .probe = mtk_hsdma_probe,
+ .remove = mtk_hsdma_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = mtk_hsdma_match,
+ },
+};
+module_platform_driver(mtk_hsdma_driver);
+
+MODULE_DESCRIPTION("MediaTek High-Speed DMA Controller Driver");
+MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index d7327fd5f445..de1fd59fe136 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -1510,7 +1510,7 @@ static void pl330_dotask(unsigned long data)
/* Returns 1 if state was updated, 0 otherwise */
static int pl330_update(struct pl330_dmac *pl330)
{
- struct dma_pl330_desc *descdone, *tmp;
+ struct dma_pl330_desc *descdone;
unsigned long flags;
void __iomem *regs;
u32 val;
@@ -1588,7 +1588,9 @@ static int pl330_update(struct pl330_dmac *pl330)
}
/* Now that we are in no hurry, do the callbacks */
- list_for_each_entry_safe(descdone, tmp, &pl330->req_done, rqd) {
+ while (!list_empty(&pl330->req_done)) {
+ descdone = list_first_entry(&pl330->req_done,
+ struct dma_pl330_desc, rqd);
list_del(&descdone->rqd);
spin_unlock_irqrestore(&pl330->lock, flags);
dma_pl330_rqcb(descdone, PL330_ERR_NONE);
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
index d076940e0c69..d29275b97e84 100644
--- a/drivers/dma/qcom/bam_dma.c
+++ b/drivers/dma/qcom/bam_dma.c
@@ -393,6 +393,7 @@ struct bam_device {
struct device_dma_parameters dma_parms;
struct bam_chan *channels;
u32 num_channels;
+ u32 num_ees;
/* execution environment ID, from DT */
u32 ee;
@@ -934,12 +935,15 @@ static void bam_apply_new_config(struct bam_chan *bchan,
struct bam_device *bdev = bchan->bdev;
u32 maxburst;
- if (dir == DMA_DEV_TO_MEM)
- maxburst = bchan->slave.src_maxburst;
- else
- maxburst = bchan->slave.dst_maxburst;
+ if (!bdev->controlled_remotely) {
+ if (dir == DMA_DEV_TO_MEM)
+ maxburst = bchan->slave.src_maxburst;
+ else
+ maxburst = bchan->slave.dst_maxburst;
- writel_relaxed(maxburst, bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD));
+ writel_relaxed(maxburst,
+ bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD));
+ }
bchan->reconfigure = 0;
}
@@ -1128,15 +1132,19 @@ static int bam_init(struct bam_device *bdev)
u32 val;
/* read revision and configuration information */
- val = readl_relaxed(bam_addr(bdev, 0, BAM_REVISION)) >> NUM_EES_SHIFT;
- val &= NUM_EES_MASK;
+ if (!bdev->num_ees) {
+ val = readl_relaxed(bam_addr(bdev, 0, BAM_REVISION));
+ bdev->num_ees = (val >> NUM_EES_SHIFT) & NUM_EES_MASK;
+ }
/* check that configured EE is within range */
- if (bdev->ee >= val)
+ if (bdev->ee >= bdev->num_ees)
return -EINVAL;
- val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES));
- bdev->num_channels = val & BAM_NUM_PIPES_MASK;
+ if (!bdev->num_channels) {
+ val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES));
+ bdev->num_channels = val & BAM_NUM_PIPES_MASK;
+ }
if (bdev->controlled_remotely)
return 0;
@@ -1232,9 +1240,25 @@ static int bam_dma_probe(struct platform_device *pdev)
bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node,
"qcom,controlled-remotely");
+ if (bdev->controlled_remotely) {
+ ret = of_property_read_u32(pdev->dev.of_node, "num-channels",
+ &bdev->num_channels);
+ if (ret)
+ dev_err(bdev->dev, "num-channels unspecified in dt\n");
+
+ ret = of_property_read_u32(pdev->dev.of_node, "qcom,num-ees",
+ &bdev->num_ees);
+ if (ret)
+ dev_err(bdev->dev, "num-ees unspecified in dt\n");
+ }
+
bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk");
- if (IS_ERR(bdev->bamclk))
- return PTR_ERR(bdev->bamclk);
+ if (IS_ERR(bdev->bamclk)) {
+ if (!bdev->controlled_remotely)
+ return PTR_ERR(bdev->bamclk);
+
+ bdev->bamclk = NULL;
+ }
ret = clk_prepare_enable(bdev->bamclk);
if (ret) {
@@ -1309,6 +1333,11 @@ static int bam_dma_probe(struct platform_device *pdev)
if (ret)
goto err_unregister_dma;
+ if (bdev->controlled_remotely) {
+ pm_runtime_disable(&pdev->dev);
+ return 0;
+ }
+
pm_runtime_irq_safe(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, BAM_DMA_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(&pdev->dev);
@@ -1392,7 +1421,8 @@ static int __maybe_unused bam_dma_suspend(struct device *dev)
{
struct bam_device *bdev = dev_get_drvdata(dev);
- pm_runtime_force_suspend(dev);
+ if (!bdev->controlled_remotely)
+ pm_runtime_force_suspend(dev);
clk_unprepare(bdev->bamclk);
@@ -1408,7 +1438,8 @@ static int __maybe_unused bam_dma_resume(struct device *dev)
if (ret)
return ret;
- pm_runtime_force_resume(dev);
+ if (!bdev->controlled_remotely)
+ pm_runtime_force_resume(dev);
return 0;
}
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index d0cacdb0713e..2a2ccd9c78e4 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1301,8 +1301,17 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
* If the cookie doesn't correspond to the currently running transfer
* then the descriptor hasn't been processed yet, and the residue is
* equal to the full descriptor size.
+ * Also, a client driver is possible to call this function before
+ * rcar_dmac_isr_channel_thread() runs. In this case, the "desc.running"
+ * will be the next descriptor, and the done list will appear. So, if
+ * the argument cookie matches the done list's cookie, we can assume
+ * the residue is zero.
*/
if (cookie != desc->async_tx.cookie) {
+ list_for_each_entry(desc, &chan->desc.done, node) {
+ if (cookie == desc->async_tx.cookie)
+ return 0;
+ }
list_for_each_entry(desc, &chan->desc.pending, node) {
if (cookie == desc->async_tx.cookie)
return desc->size;
@@ -1677,8 +1686,8 @@ static const struct dev_pm_ops rcar_dmac_pm = {
* - Wait for the current transfer to complete and stop the device,
* - Resume transfers, if any.
*/
- SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(rcar_dmac_runtime_suspend, rcar_dmac_runtime_resume,
NULL)
};
diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index 786fc8fcc38e..8c5807362a25 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -5,6 +5,7 @@
*
* Copyright (C) M'boumba Cedric Madianga 2015
* Author: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
+ * Pierre-Yves Mordret <pierre-yves.mordret@st.com>
*
* License terms: GNU General Public License (GPL), version 2
*/
@@ -33,9 +34,14 @@
#define STM32_DMA_LIFCR 0x0008 /* DMA Low Int Flag Clear Reg */
#define STM32_DMA_HIFCR 0x000c /* DMA High Int Flag Clear Reg */
#define STM32_DMA_TCI BIT(5) /* Transfer Complete Interrupt */
+#define STM32_DMA_HTI BIT(4) /* Half Transfer Interrupt */
#define STM32_DMA_TEI BIT(3) /* Transfer Error Interrupt */
#define STM32_DMA_DMEI BIT(2) /* Direct Mode Error Interrupt */
#define STM32_DMA_FEI BIT(0) /* FIFO Error Interrupt */
+#define STM32_DMA_MASKI (STM32_DMA_TCI \
+ | STM32_DMA_TEI \
+ | STM32_DMA_DMEI \
+ | STM32_DMA_FEI)
/* DMA Stream x Configuration Register */
#define STM32_DMA_SCR(x) (0x0010 + 0x18 * (x)) /* x = 0..7 */
@@ -60,7 +66,8 @@
#define STM32_DMA_SCR_PINC BIT(9) /* Peripheral increment mode */
#define STM32_DMA_SCR_CIRC BIT(8) /* Circular mode */
#define STM32_DMA_SCR_PFCTRL BIT(5) /* Peripheral Flow Controller */
-#define STM32_DMA_SCR_TCIE BIT(4) /* Transfer Cplete Int Enable*/
+#define STM32_DMA_SCR_TCIE BIT(4) /* Transfer Complete Int Enable
+ */
#define STM32_DMA_SCR_TEIE BIT(2) /* Transfer Error Int Enable */
#define STM32_DMA_SCR_DMEIE BIT(1) /* Direct Mode Err Int Enable */
#define STM32_DMA_SCR_EN BIT(0) /* Stream Enable */
@@ -111,11 +118,24 @@
#define STM32_DMA_FIFO_THRESHOLD_FULL 0x03
#define STM32_DMA_MAX_DATA_ITEMS 0xffff
+/*
+ * Valid transfer starts from @0 to @0xFFFE leading to unaligned scatter
+ * gather at boundary. Thus it's safer to round down this value on FIFO
+ * size (16 Bytes)
+ */
+#define STM32_DMA_ALIGNED_MAX_DATA_ITEMS \
+ ALIGN_DOWN(STM32_DMA_MAX_DATA_ITEMS, 16)
#define STM32_DMA_MAX_CHANNELS 0x08
#define STM32_DMA_MAX_REQUEST_ID 0x08
#define STM32_DMA_MAX_DATA_PARAM 0x03
+#define STM32_DMA_FIFO_SIZE 16 /* FIFO is 16 bytes */
+#define STM32_DMA_MIN_BURST 4
#define STM32_DMA_MAX_BURST 16
+/* DMA Features */
+#define STM32_DMA_THRESHOLD_FTR_MASK GENMASK(1, 0)
+#define STM32_DMA_THRESHOLD_FTR_GET(n) ((n) & STM32_DMA_THRESHOLD_FTR_MASK)
+
enum stm32_dma_width {
STM32_DMA_BYTE,
STM32_DMA_HALF_WORD,
@@ -129,11 +149,18 @@ enum stm32_dma_burst_size {
STM32_DMA_BURST_INCR16,
};
+/**
+ * struct stm32_dma_cfg - STM32 DMA custom configuration
+ * @channel_id: channel ID
+ * @request_line: DMA request
+ * @stream_config: 32bit mask specifying the DMA channel configuration
+ * @features: 32bit mask specifying the DMA Feature list
+ */
struct stm32_dma_cfg {
u32 channel_id;
u32 request_line;
u32 stream_config;
- u32 threshold;
+ u32 features;
};
struct stm32_dma_chan_reg {
@@ -171,6 +198,9 @@ struct stm32_dma_chan {
u32 next_sg;
struct dma_slave_config dma_sconfig;
struct stm32_dma_chan_reg chan_reg;
+ u32 threshold;
+ u32 mem_burst;
+ u32 mem_width;
};
struct stm32_dma_device {
@@ -235,6 +265,85 @@ static int stm32_dma_get_width(struct stm32_dma_chan *chan,
}
}
+static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len,
+ u32 threshold)
+{
+ enum dma_slave_buswidth max_width;
+
+ if (threshold == STM32_DMA_FIFO_THRESHOLD_FULL)
+ max_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ else
+ max_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+
+ while ((buf_len < max_width || buf_len % max_width) &&
+ max_width > DMA_SLAVE_BUSWIDTH_1_BYTE)
+ max_width = max_width >> 1;
+
+ return max_width;
+}
+
+static bool stm32_dma_fifo_threshold_is_allowed(u32 burst, u32 threshold,
+ enum dma_slave_buswidth width)
+{
+ u32 remaining;
+
+ if (width != DMA_SLAVE_BUSWIDTH_UNDEFINED) {
+ if (burst != 0) {
+ /*
+ * If number of beats fit in several whole bursts
+ * this configuration is allowed.
+ */
+ remaining = ((STM32_DMA_FIFO_SIZE / width) *
+ (threshold + 1) / 4) % burst;
+
+ if (remaining == 0)
+ return true;
+ } else {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool stm32_dma_is_burst_possible(u32 buf_len, u32 threshold)
+{
+ switch (threshold) {
+ case STM32_DMA_FIFO_THRESHOLD_FULL:
+ if (buf_len >= STM32_DMA_MAX_BURST)
+ return true;
+ else
+ return false;
+ case STM32_DMA_FIFO_THRESHOLD_HALFFULL:
+ if (buf_len >= STM32_DMA_MAX_BURST / 2)
+ return true;
+ else
+ return false;
+ default:
+ return false;
+ }
+}
+
+static u32 stm32_dma_get_best_burst(u32 buf_len, u32 max_burst, u32 threshold,
+ enum dma_slave_buswidth width)
+{
+ u32 best_burst = max_burst;
+
+ if (best_burst == 1 || !stm32_dma_is_burst_possible(buf_len, threshold))
+ return 0;
+
+ while ((buf_len < best_burst * width && best_burst > 1) ||
+ !stm32_dma_fifo_threshold_is_allowed(best_burst, threshold,
+ width)) {
+ if (best_burst > STM32_DMA_MIN_BURST)
+ best_burst = best_burst >> 1;
+ else
+ best_burst = 0;
+ }
+
+ return best_burst;
+}
+
static int stm32_dma_get_burst(struct stm32_dma_chan *chan, u32 maxburst)
{
switch (maxburst) {
@@ -254,12 +363,12 @@ static int stm32_dma_get_burst(struct stm32_dma_chan *chan, u32 maxburst)
}
static void stm32_dma_set_fifo_config(struct stm32_dma_chan *chan,
- u32 src_maxburst, u32 dst_maxburst)
+ u32 src_burst, u32 dst_burst)
{
chan->chan_reg.dma_sfcr &= ~STM32_DMA_SFCR_MASK;
chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_DMEIE;
- if ((!src_maxburst) && (!dst_maxburst)) {
+ if (!src_burst && !dst_burst) {
/* Using direct mode */
chan->chan_reg.dma_scr |= STM32_DMA_SCR_DMEIE;
} else {
@@ -300,7 +409,7 @@ static u32 stm32_dma_irq_status(struct stm32_dma_chan *chan)
flags = dma_isr >> (((chan->id & 2) << 3) | ((chan->id & 1) * 6));
- return flags;
+ return flags & STM32_DMA_MASKI;
}
static void stm32_dma_irq_clear(struct stm32_dma_chan *chan, u32 flags)
@@ -315,6 +424,7 @@ static void stm32_dma_irq_clear(struct stm32_dma_chan *chan, u32 flags)
* If (ch % 4) is 2 or 3, left shift the mask by 16 bits.
* If (ch % 4) is 1 or 3, additionally left shift the mask by 6 bits.
*/
+ flags &= STM32_DMA_MASKI;
dma_ifcr = flags << (((chan->id & 2) << 3) | ((chan->id & 1) * 6));
if (chan->id & 4)
@@ -429,6 +539,8 @@ static void stm32_dma_dump_reg(struct stm32_dma_chan *chan)
dev_dbg(chan2dev(chan), "SFCR: 0x%08x\n", sfcr);
}
+static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan);
+
static void stm32_dma_start_transfer(struct stm32_dma_chan *chan)
{
struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
@@ -471,6 +583,9 @@ static void stm32_dma_start_transfer(struct stm32_dma_chan *chan)
if (status)
stm32_dma_irq_clear(chan, status);
+ if (chan->desc->cyclic)
+ stm32_dma_configure_next_sg(chan);
+
stm32_dma_dump_reg(chan);
/* Start DMA */
@@ -541,13 +656,29 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid)
status = stm32_dma_irq_status(chan);
scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id));
- if ((status & STM32_DMA_TCI) && (scr & STM32_DMA_SCR_TCIE)) {
+ if (status & STM32_DMA_TCI) {
stm32_dma_irq_clear(chan, STM32_DMA_TCI);
- stm32_dma_handle_chan_done(chan);
-
- } else {
+ if (scr & STM32_DMA_SCR_TCIE)
+ stm32_dma_handle_chan_done(chan);
+ status &= ~STM32_DMA_TCI;
+ }
+ if (status & STM32_DMA_HTI) {
+ stm32_dma_irq_clear(chan, STM32_DMA_HTI);
+ status &= ~STM32_DMA_HTI;
+ }
+ if (status & STM32_DMA_FEI) {
+ stm32_dma_irq_clear(chan, STM32_DMA_FEI);
+ status &= ~STM32_DMA_FEI;
+ if (!(scr & STM32_DMA_SCR_EN))
+ dev_err(chan2dev(chan), "FIFO Error\n");
+ else
+ dev_dbg(chan2dev(chan), "FIFO over/underrun\n");
+ }
+ if (status) {
stm32_dma_irq_clear(chan, status);
dev_err(chan2dev(chan), "DMA error: status=0x%08x\n", status);
+ if (!(scr & STM32_DMA_SCR_EN))
+ dev_err(chan2dev(chan), "chan disabled by HW\n");
}
spin_unlock(&chan->vchan.lock);
@@ -564,45 +695,59 @@ static void stm32_dma_issue_pending(struct dma_chan *c)
if (vchan_issue_pending(&chan->vchan) && !chan->desc && !chan->busy) {
dev_dbg(chan2dev(chan), "vchan %p: issued\n", &chan->vchan);
stm32_dma_start_transfer(chan);
- if (chan->desc->cyclic)
- stm32_dma_configure_next_sg(chan);
+
}
spin_unlock_irqrestore(&chan->vchan.lock, flags);
}
static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
enum dma_transfer_direction direction,
- enum dma_slave_buswidth *buswidth)
+ enum dma_slave_buswidth *buswidth,
+ u32 buf_len)
{
enum dma_slave_buswidth src_addr_width, dst_addr_width;
int src_bus_width, dst_bus_width;
int src_burst_size, dst_burst_size;
- u32 src_maxburst, dst_maxburst;
- u32 dma_scr = 0;
+ u32 src_maxburst, dst_maxburst, src_best_burst, dst_best_burst;
+ u32 dma_scr, threshold;
src_addr_width = chan->dma_sconfig.src_addr_width;
dst_addr_width = chan->dma_sconfig.dst_addr_width;
src_maxburst = chan->dma_sconfig.src_maxburst;
dst_maxburst = chan->dma_sconfig.dst_maxburst;
+ threshold = chan->threshold;
switch (direction) {
case DMA_MEM_TO_DEV:
+ /* Set device data size */
dst_bus_width = stm32_dma_get_width(chan, dst_addr_width);
if (dst_bus_width < 0)
return dst_bus_width;
- dst_burst_size = stm32_dma_get_burst(chan, dst_maxburst);
+ /* Set device burst size */
+ dst_best_burst = stm32_dma_get_best_burst(buf_len,
+ dst_maxburst,
+ threshold,
+ dst_addr_width);
+
+ dst_burst_size = stm32_dma_get_burst(chan, dst_best_burst);
if (dst_burst_size < 0)
return dst_burst_size;
- if (!src_addr_width)
- src_addr_width = dst_addr_width;
-
+ /* Set memory data size */
+ src_addr_width = stm32_dma_get_max_width(buf_len, threshold);
+ chan->mem_width = src_addr_width;
src_bus_width = stm32_dma_get_width(chan, src_addr_width);
if (src_bus_width < 0)
return src_bus_width;
- src_burst_size = stm32_dma_get_burst(chan, src_maxburst);
+ /* Set memory burst size */
+ src_maxburst = STM32_DMA_MAX_BURST;
+ src_best_burst = stm32_dma_get_best_burst(buf_len,
+ src_maxburst,
+ threshold,
+ src_addr_width);
+ src_burst_size = stm32_dma_get_burst(chan, src_best_burst);
if (src_burst_size < 0)
return src_burst_size;
@@ -612,27 +757,46 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
STM32_DMA_SCR_PBURST(dst_burst_size) |
STM32_DMA_SCR_MBURST(src_burst_size);
+ /* Set FIFO threshold */
+ chan->chan_reg.dma_sfcr &= ~STM32_DMA_SFCR_FTH_MASK;
+ chan->chan_reg.dma_sfcr |= STM32_DMA_SFCR_FTH(threshold);
+
+ /* Set peripheral address */
chan->chan_reg.dma_spar = chan->dma_sconfig.dst_addr;
*buswidth = dst_addr_width;
break;
case DMA_DEV_TO_MEM:
+ /* Set device data size */
src_bus_width = stm32_dma_get_width(chan, src_addr_width);
if (src_bus_width < 0)
return src_bus_width;
- src_burst_size = stm32_dma_get_burst(chan, src_maxburst);
+ /* Set device burst size */
+ src_best_burst = stm32_dma_get_best_burst(buf_len,
+ src_maxburst,
+ threshold,
+ src_addr_width);
+ chan->mem_burst = src_best_burst;
+ src_burst_size = stm32_dma_get_burst(chan, src_best_burst);
if (src_burst_size < 0)
return src_burst_size;
- if (!dst_addr_width)
- dst_addr_width = src_addr_width;
-
+ /* Set memory data size */
+ dst_addr_width = stm32_dma_get_max_width(buf_len, threshold);
+ chan->mem_width = dst_addr_width;
dst_bus_width = stm32_dma_get_width(chan, dst_addr_width);
if (dst_bus_width < 0)
return dst_bus_width;
- dst_burst_size = stm32_dma_get_burst(chan, dst_maxburst);
+ /* Set memory burst size */
+ dst_maxburst = STM32_DMA_MAX_BURST;
+ dst_best_burst = stm32_dma_get_best_burst(buf_len,
+ dst_maxburst,
+ threshold,
+ dst_addr_width);
+ chan->mem_burst = dst_best_burst;
+ dst_burst_size = stm32_dma_get_burst(chan, dst_best_burst);
if (dst_burst_size < 0)
return dst_burst_size;
@@ -642,6 +806,11 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
STM32_DMA_SCR_PBURST(src_burst_size) |
STM32_DMA_SCR_MBURST(dst_burst_size);
+ /* Set FIFO threshold */
+ chan->chan_reg.dma_sfcr &= ~STM32_DMA_SFCR_FTH_MASK;
+ chan->chan_reg.dma_sfcr |= STM32_DMA_SFCR_FTH(threshold);
+
+ /* Set peripheral address */
chan->chan_reg.dma_spar = chan->dma_sconfig.src_addr;
*buswidth = chan->dma_sconfig.src_addr_width;
break;
@@ -651,8 +820,9 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan,
return -EINVAL;
}
- stm32_dma_set_fifo_config(chan, src_maxburst, dst_maxburst);
+ stm32_dma_set_fifo_config(chan, src_best_burst, dst_best_burst);
+ /* Set DMA control register */
chan->chan_reg.dma_scr &= ~(STM32_DMA_SCR_DIR_MASK |
STM32_DMA_SCR_PSIZE_MASK | STM32_DMA_SCR_MSIZE_MASK |
STM32_DMA_SCR_PBURST_MASK | STM32_DMA_SCR_MBURST_MASK);
@@ -692,10 +862,6 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg(
if (!desc)
return NULL;
- ret = stm32_dma_set_xfer_param(chan, direction, &buswidth);
- if (ret < 0)
- goto err;
-
/* Set peripheral flow controller */
if (chan->dma_sconfig.device_fc)
chan->chan_reg.dma_scr |= STM32_DMA_SCR_PFCTRL;
@@ -703,10 +869,15 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg(
chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL;
for_each_sg(sgl, sg, sg_len, i) {
+ ret = stm32_dma_set_xfer_param(chan, direction, &buswidth,
+ sg_dma_len(sg));
+ if (ret < 0)
+ goto err;
+
desc->sg_req[i].len = sg_dma_len(sg);
nb_data_items = desc->sg_req[i].len / buswidth;
- if (nb_data_items > STM32_DMA_MAX_DATA_ITEMS) {
+ if (nb_data_items > STM32_DMA_ALIGNED_MAX_DATA_ITEMS) {
dev_err(chan2dev(chan), "nb items not supported\n");
goto err;
}
@@ -767,12 +938,12 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic(
return NULL;
}
- ret = stm32_dma_set_xfer_param(chan, direction, &buswidth);
+ ret = stm32_dma_set_xfer_param(chan, direction, &buswidth, period_len);
if (ret < 0)
return NULL;
nb_data_items = period_len / buswidth;
- if (nb_data_items > STM32_DMA_MAX_DATA_ITEMS) {
+ if (nb_data_items > STM32_DMA_ALIGNED_MAX_DATA_ITEMS) {
dev_err(chan2dev(chan), "number of items not supported\n");
return NULL;
}
@@ -816,35 +987,45 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
dma_addr_t src, size_t len, unsigned long flags)
{
struct stm32_dma_chan *chan = to_stm32_dma_chan(c);
- u32 num_sgs;
+ enum dma_slave_buswidth max_width;
struct stm32_dma_desc *desc;
size_t xfer_count, offset;
+ u32 num_sgs, best_burst, dma_burst, threshold;
int i;
- num_sgs = DIV_ROUND_UP(len, STM32_DMA_MAX_DATA_ITEMS);
+ num_sgs = DIV_ROUND_UP(len, STM32_DMA_ALIGNED_MAX_DATA_ITEMS);
desc = stm32_dma_alloc_desc(num_sgs);
if (!desc)
return NULL;
+ threshold = chan->threshold;
+
for (offset = 0, i = 0; offset < len; offset += xfer_count, i++) {
xfer_count = min_t(size_t, len - offset,
- STM32_DMA_MAX_DATA_ITEMS);
+ STM32_DMA_ALIGNED_MAX_DATA_ITEMS);
- desc->sg_req[i].len = xfer_count;
+ /* Compute best burst size */
+ max_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ best_burst = stm32_dma_get_best_burst(len, STM32_DMA_MAX_BURST,
+ threshold, max_width);
+ dma_burst = stm32_dma_get_burst(chan, best_burst);
stm32_dma_clear_reg(&desc->sg_req[i].chan_reg);
desc->sg_req[i].chan_reg.dma_scr =
STM32_DMA_SCR_DIR(STM32_DMA_MEM_TO_MEM) |
+ STM32_DMA_SCR_PBURST(dma_burst) |
+ STM32_DMA_SCR_MBURST(dma_burst) |
STM32_DMA_SCR_MINC |
STM32_DMA_SCR_PINC |
STM32_DMA_SCR_TCIE |
STM32_DMA_SCR_TEIE;
- desc->sg_req[i].chan_reg.dma_sfcr = STM32_DMA_SFCR_DMDIS |
- STM32_DMA_SFCR_FTH(STM32_DMA_FIFO_THRESHOLD_FULL) |
- STM32_DMA_SFCR_FEIE;
+ desc->sg_req[i].chan_reg.dma_sfcr |= STM32_DMA_SFCR_MASK;
+ desc->sg_req[i].chan_reg.dma_sfcr |=
+ STM32_DMA_SFCR_FTH(threshold);
desc->sg_req[i].chan_reg.dma_spar = src + offset;
desc->sg_req[i].chan_reg.dma_sm0ar = dest + offset;
desc->sg_req[i].chan_reg.dma_sndtr = xfer_count;
+ desc->sg_req[i].len = xfer_count;
}
desc->num_sgs = num_sgs;
@@ -869,6 +1050,7 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
struct stm32_dma_desc *desc,
u32 next_sg)
{
+ u32 modulo, burst_size;
u32 residue = 0;
int i;
@@ -876,8 +1058,10 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
* In cyclic mode, for the last period, residue = remaining bytes from
* NDTR
*/
- if (chan->desc->cyclic && next_sg == 0)
- return stm32_dma_get_remaining_bytes(chan);
+ if (chan->desc->cyclic && next_sg == 0) {
+ residue = stm32_dma_get_remaining_bytes(chan);
+ goto end;
+ }
/*
* For all other periods in cyclic mode, and in sg mode,
@@ -888,6 +1072,15 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
residue += desc->sg_req[i].len;
residue += stm32_dma_get_remaining_bytes(chan);
+end:
+ if (!chan->mem_burst)
+ return residue;
+
+ burst_size = chan->mem_burst * chan->mem_width;
+ modulo = residue % burst_size;
+ if (modulo)
+ residue = residue - modulo + burst_size;
+
return residue;
}
@@ -902,7 +1095,7 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c,
u32 residue = 0;
status = dma_cookie_status(c, cookie, state);
- if ((status == DMA_COMPLETE) || (!state))
+ if (status == DMA_COMPLETE || !state)
return status;
spin_lock_irqsave(&chan->vchan.lock, flags);
@@ -966,7 +1159,7 @@ static void stm32_dma_desc_free(struct virt_dma_desc *vdesc)
}
static void stm32_dma_set_config(struct stm32_dma_chan *chan,
- struct stm32_dma_cfg *cfg)
+ struct stm32_dma_cfg *cfg)
{
stm32_dma_clear_reg(&chan->chan_reg);
@@ -976,7 +1169,7 @@ static void stm32_dma_set_config(struct stm32_dma_chan *chan,
/* Enable Interrupts */
chan->chan_reg.dma_scr |= STM32_DMA_SCR_TEIE | STM32_DMA_SCR_TCIE;
- chan->chan_reg.dma_sfcr = cfg->threshold & STM32_DMA_SFCR_FTH_MASK;
+ chan->threshold = STM32_DMA_THRESHOLD_FTR_GET(cfg->features);
}
static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
@@ -996,10 +1189,10 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
cfg.channel_id = dma_spec->args[0];
cfg.request_line = dma_spec->args[1];
cfg.stream_config = dma_spec->args[2];
- cfg.threshold = dma_spec->args[3];
+ cfg.features = dma_spec->args[3];
- if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) ||
- (cfg.request_line >= STM32_DMA_MAX_REQUEST_ID)) {
+ if (cfg.channel_id >= STM32_DMA_MAX_CHANNELS ||
+ cfg.request_line >= STM32_DMA_MAX_REQUEST_ID) {
dev_err(dev, "Bad channel and/or request id\n");
return NULL;
}
diff --git a/drivers/firmware/broadcom/Kconfig b/drivers/firmware/broadcom/Kconfig
index 3c7e5b741e37..f77cdb3a041f 100644
--- a/drivers/firmware/broadcom/Kconfig
+++ b/drivers/firmware/broadcom/Kconfig
@@ -13,6 +13,7 @@ config BCM47XX_NVRAM
config BCM47XX_SPROM
bool "Broadcom SPROM driver"
depends on BCM47XX_NVRAM
+ select GENERIC_NET_UTILS
help
Broadcom devices store configuration data in SPROM. Accessing it is
specific to the bus host type, e.g. PCI(e) devices have it mapped in
diff --git a/drivers/firmware/broadcom/bcm47xx_sprom.c b/drivers/firmware/broadcom/bcm47xx_sprom.c
index 62aa3cf09b4d..4787f86c8ac1 100644
--- a/drivers/firmware/broadcom/bcm47xx_sprom.c
+++ b/drivers/firmware/broadcom/bcm47xx_sprom.c
@@ -137,20 +137,6 @@ static void nvram_read_leddc(const char *prefix, const char *name,
*leddc_off_time = (val >> 16) & 0xff;
}
-static void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
-{
- if (strchr(buf, ':'))
- sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
- &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
- &macaddr[5]);
- else if (strchr(buf, '-'))
- sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
- &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
- &macaddr[5]);
- else
- pr_warn("Can not parse mac address: %s\n", buf);
-}
-
static void nvram_read_macaddr(const char *prefix, const char *name,
u8 val[6], bool fallback)
{
@@ -161,7 +147,9 @@ static void nvram_read_macaddr(const char *prefix, const char *name,
if (err < 0)
return;
- bcm47xx_nvram_parse_macaddr(buf, val);
+ strreplace(buf, '-', ':');
+ if (!mac_pton(buf, val))
+ pr_warn("Can not parse mac address: %s\n", buf);
}
static void nvram_read_alpha2(const char *prefix, const char *name,
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index a4f68affc13b..d39400e5bc42 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -89,14 +89,14 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname)
*/
if (to_adreno_gpu(gpu)->fwloc == FW_LOCATION_LEGACY) {
ret = qcom_mdt_load(dev, fw, fwname, GPU_PAS_ID,
- mem_region, mem_phys, mem_size);
+ mem_region, mem_phys, mem_size, NULL);
} else {
char newname[strlen("qcom/") + strlen(fwname) + 1];
sprintf(newname, "qcom/%s", fwname);
ret = qcom_mdt_load(dev, fw, newname, GPU_PAS_ID,
- mem_region, mem_phys, mem_size);
+ mem_region, mem_phys, mem_size, NULL);
}
if (ret)
goto out;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 033e57366d56..f249a4428458 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1231,8 +1231,9 @@ config SENSORS_NCT6775
help
If you say yes here you get support for the hardware monitoring
functionality of the Nuvoton NCT6106D, NCT6775F, NCT6776F, NCT6779D,
- NCT6791D, NCT6792D, NCT6793D, and compatible Super-I/O chips. This
- driver replaces the w83627ehf driver for NCT6775F and NCT6776F.
+ NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D, and compatible
+ Super-I/O chips. This driver replaces the w83627ehf driver for
+ NCT6775F and NCT6776F.
This driver can also be built as a module. If so, the module
will be called nct6775.
diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
index 6d1208b2b6d2..6c83c385a7ca 100644
--- a/drivers/hwmon/g762.c
+++ b/drivers/hwmon/g762.c
@@ -128,7 +128,6 @@ enum g762_regs {
G762_REG_FAN_CMD2_GEAR_MODE_1)) >> 2))
struct g762_data {
- struct device *hwmon_dev;
struct i2c_client *client;
struct clk *clk;
@@ -594,6 +593,14 @@ MODULE_DEVICE_TABLE(of, g762_dt_match);
* call to g762_of_clock_disable(). Note that a reference to clock is kept
* in our private data structure to be used in this function.
*/
+static void g762_of_clock_disable(void *data)
+{
+ struct g762_data *g762 = data;
+
+ clk_disable_unprepare(g762->clk);
+ clk_put(g762->clk);
+}
+
static int g762_of_clock_enable(struct i2c_client *client)
{
struct g762_data *data;
@@ -626,6 +633,7 @@ static int g762_of_clock_enable(struct i2c_client *client)
data = i2c_get_clientdata(client);
data->clk = clk;
+ devm_add_action(&client->dev, g762_of_clock_disable, data);
return 0;
clk_unprep:
@@ -637,17 +645,6 @@ static int g762_of_clock_enable(struct i2c_client *client)
return ret;
}
-static void g762_of_clock_disable(struct i2c_client *client)
-{
- struct g762_data *data = i2c_get_clientdata(client);
-
- if (!data->clk)
- return;
-
- clk_disable_unprepare(data->clk);
- clk_put(data->clk);
-}
-
static int g762_of_prop_import_one(struct i2c_client *client,
const char *pname,
int (*psetter)(struct device *dev,
@@ -698,8 +695,6 @@ static int g762_of_clock_enable(struct i2c_client *client)
{
return 0;
}
-
-static void g762_of_clock_disable(struct i2c_client *client) { }
#endif
/*
@@ -1054,6 +1049,7 @@ static inline int g762_fan_init(struct device *dev)
static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
+ struct device *hwmon_dev;
struct g762_data *data;
int ret;
@@ -1080,35 +1076,15 @@ static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id)
return ret;
ret = g762_of_prop_import(client);
if (ret)
- goto clock_dis;
+ return ret;
/* ... or platform_data */
ret = g762_pdata_prop_import(client);
if (ret)
- goto clock_dis;
+ return ret;
- data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
data, g762_groups);
- if (IS_ERR(data->hwmon_dev)) {
- ret = PTR_ERR(data->hwmon_dev);
- goto clock_dis;
- }
-
- return 0;
-
- clock_dis:
- g762_of_clock_disable(client);
-
- return ret;
-}
-
-static int g762_remove(struct i2c_client *client)
-{
- struct g762_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- g762_of_clock_disable(client);
-
- return 0;
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static struct i2c_driver g762_driver = {
@@ -1117,7 +1093,6 @@ static struct i2c_driver g762_driver = {
.of_match_table = of_match_ptr(g762_dt_match),
},
.probe = g762_probe,
- .remove = g762_remove,
.id_table = g762_id,
};
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 2a91974a10bb..d40fe5122e94 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -52,6 +52,7 @@
*/
static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
I2C_CLIENT_END };
+enum chips { lm92, max6635 };
/* The LM92 registers */
#define LM92_REG_CONFIG 0x01 /* 8-bit, RW */
@@ -259,62 +260,6 @@ static void lm92_init_client(struct i2c_client *client)
config & 0xFE);
}
-/*
- * The MAX6635 has no identification register, so we have to use tricks
- * to identify it reliably. This is somewhat slow.
- * Note that we do NOT rely on the 2 MSB of the configuration register
- * always reading 0, as suggested by the datasheet, because it was once
- * reported not to be true.
- */
-static int max6635_check(struct i2c_client *client)
-{
- u16 temp_low, temp_high, temp_hyst, temp_crit;
- u8 conf;
- int i;
-
- /*
- * No manufacturer ID register, so a read from this address will
- * always return the last read value.
- */
- temp_low = i2c_smbus_read_word_data(client, LM92_REG_TEMP_LOW);
- if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_low)
- return 0;
- temp_high = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HIGH);
- if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_high)
- return 0;
-
- /* Limits are stored as integer values (signed, 9-bit). */
- if ((temp_low & 0x7f00) || (temp_high & 0x7f00))
- return 0;
- temp_hyst = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HYST);
- temp_crit = i2c_smbus_read_word_data(client, LM92_REG_TEMP_CRIT);
- if ((temp_hyst & 0x7f00) || (temp_crit & 0x7f00))
- return 0;
-
- /*
- * Registers addresses were found to cycle over 16-byte boundaries.
- * We don't test all registers with all offsets so as to save some
- * reads and time, but this should still be sufficient to dismiss
- * non-MAX6635 chips.
- */
- conf = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
- for (i = 16; i < 96; i *= 2) {
- if (temp_hyst != i2c_smbus_read_word_data(client,
- LM92_REG_TEMP_HYST + i - 16)
- || temp_crit != i2c_smbus_read_word_data(client,
- LM92_REG_TEMP_CRIT + i)
- || temp_low != i2c_smbus_read_word_data(client,
- LM92_REG_TEMP_LOW + i + 16)
- || temp_high != i2c_smbus_read_word_data(client,
- LM92_REG_TEMP_HIGH + i + 32)
- || conf != i2c_smbus_read_byte_data(client,
- LM92_REG_CONFIG + i))
- return 0;
- }
-
- return 1;
-}
-
static struct attribute *lm92_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
@@ -348,8 +293,6 @@ static int lm92_detect(struct i2c_client *new_client,
if ((config & 0xe0) == 0x00 && man_id == 0x0180)
pr_info("lm92: Found National Semiconductor LM92 chip\n");
- else if (max6635_check(new_client))
- pr_info("lm92: Found Maxim MAX6635 chip\n");
else
return -ENODEV;
@@ -387,8 +330,8 @@ static int lm92_probe(struct i2c_client *new_client,
*/
static const struct i2c_device_id lm92_id[] = {
- { "lm92", 0 },
- /* max6635 could be added here */
+ { "lm92", lm92 },
+ { "max6635", max6635 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm92_id);
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index c219e43b8f02..aebce560bfaf 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -41,7 +41,7 @@
* nct6792d 15 6 6 2+6 0xc910 0xc1 0x5ca3
* nct6793d 15 6 6 2+6 0xd120 0xc1 0x5ca3
* nct6795d 14 6 6 2+6 0xd350 0xc1 0x5ca3
- *
+ * nct6796d 14 7 7 2+6 0xd420 0xc1 0x5ca3
*
* #temp lists the number of monitored temperature sources (first value) plus
* the number of directly connectable temperature sensors (second value).
@@ -68,7 +68,7 @@
#define USE_ALTERNATE
enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793,
- nct6795 };
+ nct6795, nct6796 };
/* used to set data->name = nct6775_device_names[data->sio_kind] */
static const char * const nct6775_device_names[] = {
@@ -80,6 +80,7 @@ static const char * const nct6775_device_names[] = {
"nct6792",
"nct6793",
"nct6795",
+ "nct6796",
};
static const char * const nct6775_sio_names[] __initconst = {
@@ -91,6 +92,7 @@ static const char * const nct6775_sio_names[] __initconst = {
"NCT6792D",
"NCT6793D",
"NCT6795D",
+ "NCT6796D",
};
static unsigned short force_id;
@@ -125,6 +127,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
#define SIO_NCT6792_ID 0xc910
#define SIO_NCT6793_ID 0xd120
#define SIO_NCT6795_ID 0xd350
+#define SIO_NCT6796_ID 0xd420
#define SIO_ID_MASK 0xFFF0
enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
@@ -201,7 +204,7 @@ superio_exit(int ioreg)
#define NUM_REG_ALARM 7 /* Max number of alarm registers */
#define NUM_REG_BEEP 5 /* Max number of beep registers */
-#define NUM_FAN 6
+#define NUM_FAN 7
#define TEMP_SOURCE_VIRTUAL 0x1f
@@ -272,26 +275,26 @@ static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
/* Advanced Fan control, some values are common for all fans */
static const u16 NCT6775_REG_TARGET[] = {
- 0x101, 0x201, 0x301, 0x801, 0x901, 0xa01 };
+ 0x101, 0x201, 0x301, 0x801, 0x901, 0xa01, 0xb01 };
static const u16 NCT6775_REG_FAN_MODE[] = {
- 0x102, 0x202, 0x302, 0x802, 0x902, 0xa02 };
+ 0x102, 0x202, 0x302, 0x802, 0x902, 0xa02, 0xb02 };
static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
- 0x103, 0x203, 0x303, 0x803, 0x903, 0xa03 };
+ 0x103, 0x203, 0x303, 0x803, 0x903, 0xa03, 0xb03 };
static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
- 0x104, 0x204, 0x304, 0x804, 0x904, 0xa04 };
+ 0x104, 0x204, 0x304, 0x804, 0x904, 0xa04, 0xb04 };
static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
- 0x105, 0x205, 0x305, 0x805, 0x905, 0xa05 };
+ 0x105, 0x205, 0x305, 0x805, 0x905, 0xa05, 0xb05 };
static const u16 NCT6775_REG_FAN_START_OUTPUT[] = {
- 0x106, 0x206, 0x306, 0x806, 0x906, 0xa06 };
+ 0x106, 0x206, 0x306, 0x806, 0x906, 0xa06, 0xb06 };
static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
- 0x107, 0x207, 0x307, 0x807, 0x907, 0xa07 };
+ 0x107, 0x207, 0x307, 0x807, 0x907, 0xa07, 0xb07 };
static const u16 NCT6775_REG_PWM[] = {
- 0x109, 0x209, 0x309, 0x809, 0x909, 0xa09 };
+ 0x109, 0x209, 0x309, 0x809, 0x909, 0xa09, 0xb09 };
static const u16 NCT6775_REG_PWM_READ[] = {
- 0x01, 0x03, 0x11, 0x13, 0x15, 0xa09 };
+ 0x01, 0x03, 0x11, 0x13, 0x15, 0xa09, 0xb09 };
static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
@@ -314,7 +317,7 @@ static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
static const u16 NCT6775_REG_TEMP_SEL[] = {
- 0x100, 0x200, 0x300, 0x800, 0x900, 0xa00 };
+ 0x100, 0x200, 0x300, 0x800, 0x900, 0xa00, 0xb00 };
static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
0x139, 0x239, 0x339, 0x839, 0x939, 0xa39 };
@@ -330,9 +333,9 @@ static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
static const u16 NCT6775_REG_AUTO_TEMP[] = {
- 0x121, 0x221, 0x321, 0x821, 0x921, 0xa21 };
+ 0x121, 0x221, 0x321, 0x821, 0x921, 0xa21, 0xb21 };
static const u16 NCT6775_REG_AUTO_PWM[] = {
- 0x127, 0x227, 0x327, 0x827, 0x927, 0xa27 };
+ 0x127, 0x227, 0x327, 0x827, 0x927, 0xa27, 0xb27 };
#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
@@ -340,9 +343,9 @@ static const u16 NCT6775_REG_AUTO_PWM[] = {
static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
- 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35 };
+ 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35, 0xb35 };
static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
- 0x138, 0x238, 0x338, 0x838, 0x938, 0xa38 };
+ 0x138, 0x238, 0x338, 0x838, 0x938, 0xa38, 0xb38 };
static const char *const nct6775_temp_label[] = {
"",
@@ -414,13 +417,15 @@ static const s8 NCT6776_BEEP_BITS[] = {
30, 31 }; /* intrusion0, intrusion1 */
static const u16 NCT6776_REG_TOLERANCE_H[] = {
- 0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c };
+ 0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c, 0xb0c };
static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 };
static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
-static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
-static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
+static const u16 NCT6776_REG_FAN_MIN[] = {
+ 0x63a, 0x63c, 0x63e, 0x640, 0x642, 0x64a, 0x64c };
+static const u16 NCT6776_REG_FAN_PULSES[] = {
+ 0x644, 0x645, 0x646, 0x647, 0x648, 0x649, 0 };
static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e };
@@ -495,15 +500,15 @@ static const s8 NCT6779_BEEP_BITS[] = {
30, 31 }; /* intrusion0, intrusion1 */
static const u16 NCT6779_REG_FAN[] = {
- 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba };
+ 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba, 0x660 };
static const u16 NCT6779_REG_FAN_PULSES[] = {
- 0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
+ 0x644, 0x645, 0x646, 0x647, 0x648, 0x649, 0 };
static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
- 0x136, 0x236, 0x336, 0x836, 0x936, 0xa36 };
+ 0x136, 0x236, 0x336, 0x836, 0x936, 0xa36, 0xb36 };
#define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01
static const u16 NCT6779_REG_CRITICAL_PWM[] = {
- 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37 };
+ 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37, 0xb37 };
static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
static const u16 NCT6779_REG_TEMP_MON[] = { 0x73, 0x75, 0x77, 0x79, 0x7b };
@@ -570,12 +575,12 @@ static const u16 NCT6779_REG_TEMP_CRIT[32] = {
#define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28
-static const u16 NCT6791_REG_WEIGHT_TEMP_SEL[6] = { 0, 0x239 };
-static const u16 NCT6791_REG_WEIGHT_TEMP_STEP[6] = { 0, 0x23a };
-static const u16 NCT6791_REG_WEIGHT_TEMP_STEP_TOL[6] = { 0, 0x23b };
-static const u16 NCT6791_REG_WEIGHT_DUTY_STEP[6] = { 0, 0x23c };
-static const u16 NCT6791_REG_WEIGHT_TEMP_BASE[6] = { 0, 0x23d };
-static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[6] = { 0, 0x23e };
+static const u16 NCT6791_REG_WEIGHT_TEMP_SEL[NUM_FAN] = { 0, 0x239 };
+static const u16 NCT6791_REG_WEIGHT_TEMP_STEP[NUM_FAN] = { 0, 0x23a };
+static const u16 NCT6791_REG_WEIGHT_TEMP_STEP_TOL[NUM_FAN] = { 0, 0x23b };
+static const u16 NCT6791_REG_WEIGHT_DUTY_STEP[NUM_FAN] = { 0, 0x23c };
+static const u16 NCT6791_REG_WEIGHT_TEMP_BASE[NUM_FAN] = { 0, 0x23d };
+static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[NUM_FAN] = { 0, 0x23e };
static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
0x459, 0x45A, 0x45B, 0x568, 0x45D };
@@ -707,6 +712,43 @@ static const char *const nct6795_temp_label[] = {
#define NCT6795_TEMP_MASK 0xbfffff7e
+static const char *const nct6796_temp_label[] = {
+ "",
+ "SYSTIN",
+ "CPUTIN",
+ "AUXTIN0",
+ "AUXTIN1",
+ "AUXTIN2",
+ "AUXTIN3",
+ "AUXTIN4",
+ "SMBUSMASTER 0",
+ "SMBUSMASTER 1",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "PECI Agent 0",
+ "PECI Agent 1",
+ "PCH_CHIP_CPU_MAX_TEMP",
+ "PCH_CHIP_TEMP",
+ "PCH_CPU_TEMP",
+ "PCH_MCH_TEMP",
+ "PCH_DIM0_TEMP",
+ "PCH_DIM1_TEMP",
+ "PCH_DIM2_TEMP",
+ "PCH_DIM3_TEMP",
+ "BYTE_TEMP0",
+ "BYTE_TEMP1",
+ "PECI Agent 0 Calibration",
+ "PECI Agent 1 Calibration",
+ "",
+ "Virtual_TEMP"
+};
+
+#define NCT6796_TEMP_MASK 0xbfff03fe
+
/* NCT6102D/NCT6106D specific data */
#define NCT6106_REG_VBAT 0x318
@@ -1231,11 +1273,13 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg)
case nct6792:
case nct6793:
case nct6795:
+ case nct6796:
return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
reg == 0x402 ||
reg == 0x63a || reg == 0x63c || reg == 0x63e ||
- reg == 0x640 || reg == 0x642 ||
+ reg == 0x640 || reg == 0x642 || reg == 0x64a ||
+ reg == 0x64c || reg == 0x660 ||
reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
reg == 0x7b || reg == 0x7d;
}
@@ -1469,7 +1513,7 @@ static void nct6775_update_pwm(struct device *dev)
duty_is_dc = data->REG_PWM_MODE[i] &&
(nct6775_read_value(data, data->REG_PWM_MODE[i])
& data->PWM_MODE_MASK[i]);
- data->pwm_mode[i] = duty_is_dc;
+ data->pwm_mode[i] = !duty_is_dc;
fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
@@ -1584,6 +1628,7 @@ static void nct6775_update_pwm_limits(struct device *dev)
case nct6792:
case nct6793:
case nct6795:
+ case nct6796:
reg = nct6775_read_value(data,
data->REG_CRITICAL_PWM_ENABLE[i]);
if (reg & data->CRITICAL_PWM_ENABLE_MASK)
@@ -2092,6 +2137,8 @@ static umode_t nct6775_fan_is_visible(struct kobject *kobj,
return 0;
if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
return 0;
+ if (nr == 3 && !data->REG_FAN_PULSES[fan])
+ return 0;
if (nr == 4 && !(data->has_fan_min & BIT(fan)))
return 0;
if (nr == 5 && data->kind != nct6775)
@@ -2350,7 +2397,7 @@ show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
struct nct6775_data *data = nct6775_update_device(dev);
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
- return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
+ return sprintf(buf, "%d\n", data->pwm_mode[sattr->index]);
}
static ssize_t
@@ -2371,9 +2418,9 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
if (val > 1)
return -EINVAL;
- /* Setting DC mode is not supported for all chips/channels */
+ /* Setting DC mode (0) is not supported for all chips/channels */
if (data->REG_PWM_MODE[nr] == 0) {
- if (val)
+ if (!val)
return -EINVAL;
return count;
}
@@ -2382,7 +2429,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
data->pwm_mode[nr] = val;
reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
reg &= ~data->PWM_MODE_MASK[nr];
- if (val)
+ if (!val)
reg |= data->PWM_MODE_MASK[nr];
nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
mutex_unlock(&data->update_lock);
@@ -3004,6 +3051,7 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr,
case nct6792:
case nct6793:
case nct6795:
+ case nct6796:
nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
val);
reg = nct6775_read_value(data,
@@ -3358,8 +3406,10 @@ static inline void nct6775_init_device(struct nct6775_data *data)
static void
nct6775_check_fan_inputs(struct nct6775_data *data)
{
- bool fan3pin, fan4pin, fan4min, fan5pin, fan6pin;
- bool pwm3pin, pwm4pin, pwm5pin, pwm6pin;
+ bool fan3pin = false, fan4pin = false, fan4min = false;
+ bool fan5pin = false, fan6pin = false, fan7pin = false;
+ bool pwm3pin = false, pwm4pin = false, pwm5pin = false;
+ bool pwm6pin = false, pwm7pin = false;
int sioreg = data->sioreg;
int regval;
@@ -3376,12 +3426,6 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
/* On NCT6775, fan4 shares pins with the fdc interface */
fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80);
- fan4min = false;
- fan5pin = false;
- fan6pin = false;
- pwm4pin = false;
- pwm5pin = false;
- pwm6pin = false;
} else if (data->kind == nct6776) {
bool gpok = superio_inb(sioreg, 0x27) & 0x80;
const char *board_vendor, *board_name;
@@ -3421,25 +3465,15 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
fan5pin = superio_inb(sioreg, 0x1C) & 0x02;
fan4min = fan4pin;
- fan6pin = false;
pwm3pin = fan3pin;
- pwm4pin = false;
- pwm5pin = false;
- pwm6pin = false;
} else if (data->kind == nct6106) {
regval = superio_inb(sioreg, 0x24);
fan3pin = !(regval & 0x80);
pwm3pin = regval & 0x08;
-
- fan4pin = false;
- fan4min = false;
- fan5pin = false;
- fan6pin = false;
- pwm4pin = false;
- pwm5pin = false;
- pwm6pin = false;
- } else { /* NCT6779D, NCT6791D, NCT6792D, NCT6793D, or NCT6795D */
- int regval_1b, regval_2a, regval_eb;
+ } else {
+ /* NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D */
+ int regval_1b, regval_2a, regval_2f;
+ bool dsw_en;
regval = superio_inb(sioreg, 0x1c);
@@ -3460,31 +3494,60 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
break;
case nct6793:
case nct6795:
+ case nct6796:
regval_1b = superio_inb(sioreg, 0x1b);
regval_2a = superio_inb(sioreg, 0x2a);
+ regval_2f = superio_inb(sioreg, 0x2f);
+ dsw_en = regval_2f & BIT(3);
if (!pwm5pin)
pwm5pin = regval & BIT(7);
- fan6pin = regval & BIT(1);
- pwm6pin = regval & BIT(0);
+
if (!fan5pin)
fan5pin = regval_1b & BIT(5);
superio_select(sioreg, NCT6775_LD_12);
- regval_eb = superio_inb(sioreg, 0xeb);
- if (!fan5pin)
- fan5pin = regval_eb & BIT(5);
- if (!pwm5pin)
- pwm5pin = (regval_eb & BIT(4)) &&
- !(regval_2a & BIT(0));
- if (!fan6pin)
- fan6pin = regval_eb & BIT(3);
- if (!pwm6pin)
- pwm6pin = regval_eb & BIT(2);
+ if (data->kind != nct6796) {
+ int regval_eb = superio_inb(sioreg, 0xeb);
+
+ if (!dsw_en) {
+ fan6pin = regval & BIT(1);
+ pwm6pin = regval & BIT(0);
+ }
+
+ if (!fan5pin)
+ fan5pin = regval_eb & BIT(5);
+ if (!pwm5pin)
+ pwm5pin = (regval_eb & BIT(4)) &&
+ !(regval_2a & BIT(0));
+ if (!fan6pin)
+ fan6pin = regval_eb & BIT(3);
+ if (!pwm6pin)
+ pwm6pin = regval_eb & BIT(2);
+ }
+
+ if (data->kind == nct6795 || data->kind == nct6796) {
+ int regval_ed = superio_inb(sioreg, 0xed);
+
+ if (!fan6pin)
+ fan6pin = (regval_2a & BIT(4)) &&
+ (!dsw_en ||
+ (dsw_en && (regval_ed & BIT(4))));
+ if (!pwm6pin)
+ pwm6pin = (regval_2a & BIT(3)) &&
+ (regval_ed & BIT(2));
+ }
+
+ if (data->kind == nct6796) {
+ int regval_1d = superio_inb(sioreg, 0x1d);
+ int regval_2b = superio_inb(sioreg, 0x2b);
+
+ fan7pin = !(regval_2b & BIT(2));
+ pwm7pin = !(regval_1d & (BIT(2) | BIT(3)));
+ }
+
break;
default: /* NCT6779D */
- fan6pin = false;
- pwm6pin = false;
break;
}
@@ -3493,11 +3556,11 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
/* fan 1 and 2 (0x03) are always present */
data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |
- (fan5pin << 4) | (fan6pin << 5);
+ (fan5pin << 4) | (fan6pin << 5) | (fan7pin << 6);
data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |
- (fan5pin << 4);
+ (fan5pin << 4) | (fan6pin << 5) | (fan7pin << 6);
data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |
- (pwm5pin << 4) | (pwm6pin << 5);
+ (pwm5pin << 4) | (pwm6pin << 5) | (pwm7pin << 6);
}
static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
@@ -3856,8 +3919,9 @@ static int nct6775_probe(struct platform_device *pdev)
case nct6792:
case nct6793:
case nct6795:
+ case nct6796:
data->in_num = 15;
- data->pwm_num = 6;
+ data->pwm_num = (data->kind == nct6796) ? 7 : 6;
data->auto_pwm_num = 4;
data->has_fan_div = false;
data->temp_fixed_num = 6;
@@ -3891,6 +3955,10 @@ static int nct6775_probe(struct platform_device *pdev)
data->temp_label = nct6795_temp_label;
data->temp_mask = NCT6795_TEMP_MASK;
break;
+ case nct6796:
+ data->temp_label = nct6796_temp_label;
+ data->temp_mask = NCT6796_TEMP_MASK;
+ break;
}
data->REG_CONFIG = NCT6775_REG_CONFIG;
@@ -4159,6 +4227,7 @@ static int nct6775_probe(struct platform_device *pdev)
case nct6792:
case nct6793:
case nct6795:
+ case nct6796:
break;
}
@@ -4193,6 +4262,7 @@ static int nct6775_probe(struct platform_device *pdev)
case nct6792:
case nct6793:
case nct6795:
+ case nct6796:
tmp |= 0x7e;
break;
}
@@ -4291,7 +4361,8 @@ static int __maybe_unused nct6775_resume(struct device *dev)
superio_outb(sioreg, SIO_REG_ENABLE, data->sio_reg_enable);
if (data->kind == nct6791 || data->kind == nct6792 ||
- data->kind == nct6793 || data->kind == nct6795)
+ data->kind == nct6793 || data->kind == nct6795 ||
+ data->kind == nct6796)
nct6791_enable_io_mapping(sioreg);
superio_exit(sioreg);
@@ -4391,6 +4462,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
case SIO_NCT6795_ID:
sio_data->kind = nct6795;
break;
+ case SIO_NCT6796_ID:
+ sio_data->kind = nct6796;
+ break;
default:
if (val != 0xffff)
pr_debug("unsupported chip ID: 0x%04x\n", val);
@@ -4417,7 +4491,8 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
}
if (sio_data->kind == nct6791 || sio_data->kind == nct6792 ||
- sio_data->kind == nct6793 || sio_data->kind == nct6795)
+ sio_data->kind == nct6793 || sio_data->kind == nct6795 ||
+ sio_data->kind == nct6796)
nct6791_enable_io_mapping(sioaddr);
superio_exit(sioaddr);
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 6e4298e99222..e71aec69e76e 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -31,8 +31,8 @@ config SENSORS_ADM1275
default n
help
If you say yes here you get hardware monitoring support for Analog
- Devices ADM1075, ADM1275, ADM1276, ADM1278, ADM1293, and ADM1294
- Hot-Swap Controller and Digital Power Monitors.
+ Devices ADM1075, ADM1272, ADM1275, ADM1276, ADM1278, ADM1293,
+ and ADM1294 Hot-Swap Controller and Digital Power Monitors.
This driver can also be built as a module. If so, the module will
be called adm1275.
diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
index 00d6995af4c2..13600fa79e7f 100644
--- a/drivers/hwmon/pmbus/adm1275.c
+++ b/drivers/hwmon/pmbus/adm1275.c
@@ -3,6 +3,7 @@
* and Digital Power Monitor
*
* Copyright (c) 2011 Ericsson AB.
+ * Copyright (c) 2018 Guenter Roeck
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,7 +25,7 @@
#include <linux/bitops.h>
#include "pmbus.h"
-enum chips { adm1075, adm1275, adm1276, adm1278, adm1293, adm1294 };
+enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 };
#define ADM1275_MFR_STATUS_IOUT_WARN2 BIT(0)
#define ADM1293_MFR_STATUS_VAUX_UV_WARN BIT(5)
@@ -41,6 +42,8 @@ enum chips { adm1075, adm1275, adm1276, adm1278, adm1293, adm1294 };
#define ADM1075_IRANGE_25 BIT(3)
#define ADM1075_IRANGE_MASK (BIT(3) | BIT(4))
+#define ADM1272_IRANGE BIT(0)
+
#define ADM1278_TEMP1_EN BIT(3)
#define ADM1278_VIN_EN BIT(2)
#define ADM1278_VOUT_EN BIT(1)
@@ -105,6 +108,19 @@ static const struct coefficients adm1075_coefficients[] = {
[4] = { 4279, 0, -1 }, /* power, irange50 */
};
+static const struct coefficients adm1272_coefficients[] = {
+ [0] = { 6770, 0, -2 }, /* voltage, vrange 60V */
+ [1] = { 4062, 0, -2 }, /* voltage, vrange 100V */
+ [2] = { 1326, 20480, -1 }, /* current, vsense range 15mV */
+ [3] = { 663, 20480, -1 }, /* current, vsense range 30mV */
+ [4] = { 3512, 0, -2 }, /* power, vrange 60V, irange 15mV */
+ [5] = { 21071, 0, -3 }, /* power, vrange 100V, irange 15mV */
+ [6] = { 17561, 0, -3 }, /* power, vrange 60V, irange 30mV */
+ [7] = { 10535, 0, -3 }, /* power, vrange 100V, irange 30mV */
+ [8] = { 42, 31871, -1 }, /* temperature */
+
+};
+
static const struct coefficients adm1275_coefficients[] = {
[0] = { 19199, 0, -2 }, /* voltage, vrange set */
[1] = { 6720, 0, -1 }, /* voltage, vrange not set */
@@ -154,7 +170,7 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
const struct adm1275_data *data = to_adm1275_data(info);
int ret = 0;
- if (page)
+ if (page > 0)
return -ENXIO;
switch (reg) {
@@ -240,7 +256,7 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
const struct adm1275_data *data = to_adm1275_data(info);
int ret;
- if (page)
+ if (page > 0)
return -ENXIO;
switch (reg) {
@@ -335,6 +351,7 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
static const struct i2c_device_id adm1275_id[] = {
{ "adm1075", adm1075 },
+ { "adm1272", adm1272 },
{ "adm1275", adm1275 },
{ "adm1276", adm1276 },
{ "adm1278", adm1278 },
@@ -451,6 +468,54 @@ static int adm1275_probe(struct i2c_client *client,
info->func[0] |=
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
break;
+ case adm1272:
+ data->have_vout = true;
+ data->have_pin_max = true;
+ data->have_temp_max = true;
+
+ coefficients = adm1272_coefficients;
+ vindex = (config & ADM1275_VRANGE) ? 1 : 0;
+ cindex = (config & ADM1272_IRANGE) ? 3 : 2;
+ /* pindex depends on the combination of the above */
+ switch (config & (ADM1275_VRANGE | ADM1272_IRANGE)) {
+ case 0:
+ default:
+ pindex = 4;
+ break;
+ case ADM1275_VRANGE:
+ pindex = 5;
+ break;
+ case ADM1272_IRANGE:
+ pindex = 6;
+ break;
+ case ADM1275_VRANGE | ADM1272_IRANGE:
+ pindex = 7;
+ break;
+ }
+ tindex = 8;
+
+ info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT |
+ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+
+ /* Enable VOUT if not enabled (it is disabled by default) */
+ if (!(config & ADM1278_VOUT_EN)) {
+ config |= ADM1278_VOUT_EN;
+ ret = i2c_smbus_write_byte_data(client,
+ ADM1275_PMON_CONFIG,
+ config);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "Failed to enable VOUT monitoring\n");
+ return -ENODEV;
+ }
+ }
+
+ if (config & ADM1278_TEMP1_EN)
+ info->func[0] |=
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+ if (config & ADM1278_VIN_EN)
+ info->func[0] |= PMBUS_HAVE_VIN;
+ break;
case adm1275:
if (device_config & ADM1275_IOUT_WARN2_SELECT)
data->have_oc_fault = true;
diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c
index dd4883a19045..e951f9b87abb 100644
--- a/drivers/hwmon/pmbus/max8688.c
+++ b/drivers/hwmon/pmbus/max8688.c
@@ -45,7 +45,7 @@ static int max8688_read_word_data(struct i2c_client *client, int page, int reg)
{
int ret;
- if (page)
+ if (page > 0)
return -ENXIO;
switch (reg) {
diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c
index b74dbeca2e8d..70cecb06f93c 100644
--- a/drivers/hwmon/pmbus/ucd9000.c
+++ b/drivers/hwmon/pmbus/ucd9000.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/debugfs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
@@ -27,6 +28,8 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/pmbus.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include "pmbus.h"
enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 };
@@ -35,8 +38,19 @@ enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 };
#define UCD9000_NUM_PAGES 0xd6
#define UCD9000_FAN_CONFIG_INDEX 0xe7
#define UCD9000_FAN_CONFIG 0xe8
+#define UCD9000_MFR_STATUS 0xf3
+#define UCD9000_GPIO_SELECT 0xfa
+#define UCD9000_GPIO_CONFIG 0xfb
#define UCD9000_DEVICE_ID 0xfd
+/* GPIO CONFIG bits */
+#define UCD9000_GPIO_CONFIG_ENABLE BIT(0)
+#define UCD9000_GPIO_CONFIG_OUT_ENABLE BIT(1)
+#define UCD9000_GPIO_CONFIG_OUT_VALUE BIT(2)
+#define UCD9000_GPIO_CONFIG_STATUS BIT(3)
+#define UCD9000_GPIO_INPUT 0
+#define UCD9000_GPIO_OUTPUT 1
+
#define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07)
#define UCD9000_MON_PAGE(x) ((x) & 0x0f)
@@ -47,12 +61,29 @@ enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 };
#define UCD9000_NUM_FAN 4
+#define UCD9000_GPIO_NAME_LEN 16
+#define UCD9090_NUM_GPIOS 23
+#define UCD901XX_NUM_GPIOS 26
+#define UCD90910_NUM_GPIOS 26
+
+#define UCD9000_DEBUGFS_NAME_LEN 24
+#define UCD9000_GPI_COUNT 8
+
struct ucd9000_data {
u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX];
struct pmbus_driver_info info;
+#ifdef CONFIG_GPIOLIB
+ struct gpio_chip gpio;
+#endif
+ struct dentry *debugfs;
};
#define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info)
+struct ucd9000_debugfs_entry {
+ struct i2c_client *client;
+ u8 index;
+};
+
static int ucd9000_get_fan_config(struct i2c_client *client, int fan)
{
int fan_config = 0;
@@ -149,6 +180,312 @@ static const struct of_device_id ucd9000_of_match[] = {
};
MODULE_DEVICE_TABLE(of, ucd9000_of_match);
+#ifdef CONFIG_GPIOLIB
+static int ucd9000_gpio_read_config(struct i2c_client *client,
+ unsigned int offset)
+{
+ int ret;
+
+ /* No page set required */
+ ret = i2c_smbus_write_byte_data(client, UCD9000_GPIO_SELECT, offset);
+ if (ret < 0)
+ return ret;
+
+ return i2c_smbus_read_byte_data(client, UCD9000_GPIO_CONFIG);
+}
+
+static int ucd9000_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+ struct i2c_client *client = gpiochip_get_data(gc);
+ int ret;
+
+ ret = ucd9000_gpio_read_config(client, offset);
+ if (ret < 0)
+ return ret;
+
+ return !!(ret & UCD9000_GPIO_CONFIG_STATUS);
+}
+
+static void ucd9000_gpio_set(struct gpio_chip *gc, unsigned int offset,
+ int value)
+{
+ struct i2c_client *client = gpiochip_get_data(gc);
+ int ret;
+
+ ret = ucd9000_gpio_read_config(client, offset);
+ if (ret < 0) {
+ dev_dbg(&client->dev, "failed to read GPIO %d config: %d\n",
+ offset, ret);
+ return;
+ }
+
+ if (value) {
+ if (ret & UCD9000_GPIO_CONFIG_STATUS)
+ return;
+
+ ret |= UCD9000_GPIO_CONFIG_STATUS;
+ } else {
+ if (!(ret & UCD9000_GPIO_CONFIG_STATUS))
+ return;
+
+ ret &= ~UCD9000_GPIO_CONFIG_STATUS;
+ }
+
+ ret |= UCD9000_GPIO_CONFIG_ENABLE;
+
+ /* Page set not required */
+ ret = i2c_smbus_write_byte_data(client, UCD9000_GPIO_CONFIG, ret);
+ if (ret < 0) {
+ dev_dbg(&client->dev, "Failed to write GPIO %d config: %d\n",
+ offset, ret);
+ return;
+ }
+
+ ret &= ~UCD9000_GPIO_CONFIG_ENABLE;
+
+ ret = i2c_smbus_write_byte_data(client, UCD9000_GPIO_CONFIG, ret);
+ if (ret < 0)
+ dev_dbg(&client->dev, "Failed to write GPIO %d config: %d\n",
+ offset, ret);
+}
+
+static int ucd9000_gpio_get_direction(struct gpio_chip *gc,
+ unsigned int offset)
+{
+ struct i2c_client *client = gpiochip_get_data(gc);
+ int ret;
+
+ ret = ucd9000_gpio_read_config(client, offset);
+ if (ret < 0)
+ return ret;
+
+ return !(ret & UCD9000_GPIO_CONFIG_OUT_ENABLE);
+}
+
+static int ucd9000_gpio_set_direction(struct gpio_chip *gc,
+ unsigned int offset, bool direction_out,
+ int requested_out)
+{
+ struct i2c_client *client = gpiochip_get_data(gc);
+ int ret, config, out_val;
+
+ ret = ucd9000_gpio_read_config(client, offset);
+ if (ret < 0)
+ return ret;
+
+ if (direction_out) {
+ out_val = requested_out ? UCD9000_GPIO_CONFIG_OUT_VALUE : 0;
+
+ if (ret & UCD9000_GPIO_CONFIG_OUT_ENABLE) {
+ if ((ret & UCD9000_GPIO_CONFIG_OUT_VALUE) == out_val)
+ return 0;
+ } else {
+ ret |= UCD9000_GPIO_CONFIG_OUT_ENABLE;
+ }
+
+ if (out_val)
+ ret |= UCD9000_GPIO_CONFIG_OUT_VALUE;
+ else
+ ret &= ~UCD9000_GPIO_CONFIG_OUT_VALUE;
+
+ } else {
+ if (!(ret & UCD9000_GPIO_CONFIG_OUT_ENABLE))
+ return 0;
+
+ ret &= ~UCD9000_GPIO_CONFIG_OUT_ENABLE;
+ }
+
+ ret |= UCD9000_GPIO_CONFIG_ENABLE;
+ config = ret;
+
+ /* Page set not required */
+ ret = i2c_smbus_write_byte_data(client, UCD9000_GPIO_CONFIG, config);
+ if (ret < 0)
+ return ret;
+
+ config &= ~UCD9000_GPIO_CONFIG_ENABLE;
+
+ return i2c_smbus_write_byte_data(client, UCD9000_GPIO_CONFIG, config);
+}
+
+static int ucd9000_gpio_direction_input(struct gpio_chip *gc,
+ unsigned int offset)
+{
+ return ucd9000_gpio_set_direction(gc, offset, UCD9000_GPIO_INPUT, 0);
+}
+
+static int ucd9000_gpio_direction_output(struct gpio_chip *gc,
+ unsigned int offset, int val)
+{
+ return ucd9000_gpio_set_direction(gc, offset, UCD9000_GPIO_OUTPUT,
+ val);
+}
+
+static void ucd9000_probe_gpio(struct i2c_client *client,
+ const struct i2c_device_id *mid,
+ struct ucd9000_data *data)
+{
+ int rc;
+
+ switch (mid->driver_data) {
+ case ucd9090:
+ data->gpio.ngpio = UCD9090_NUM_GPIOS;
+ break;
+ case ucd90120:
+ case ucd90124:
+ case ucd90160:
+ data->gpio.ngpio = UCD901XX_NUM_GPIOS;
+ break;
+ case ucd90910:
+ data->gpio.ngpio = UCD90910_NUM_GPIOS;
+ break;
+ default:
+ return; /* GPIO support is optional. */
+ }
+
+ /*
+ * Pinmux support has not been added to the new gpio_chip.
+ * This support should be added when possible given the mux
+ * behavior of these IO devices.
+ */
+ data->gpio.label = client->name;
+ data->gpio.get_direction = ucd9000_gpio_get_direction;
+ data->gpio.direction_input = ucd9000_gpio_direction_input;
+ data->gpio.direction_output = ucd9000_gpio_direction_output;
+ data->gpio.get = ucd9000_gpio_get;
+ data->gpio.set = ucd9000_gpio_set;
+ data->gpio.can_sleep = true;
+ data->gpio.base = -1;
+ data->gpio.parent = &client->dev;
+
+ rc = devm_gpiochip_add_data(&client->dev, &data->gpio, client);
+ if (rc)
+ dev_warn(&client->dev, "Could not add gpiochip: %d\n", rc);
+}
+#else
+static void ucd9000_probe_gpio(struct i2c_client *client,
+ const struct i2c_device_id *mid,
+ struct ucd9000_data *data)
+{
+}
+#endif /* CONFIG_GPIOLIB */
+
+#ifdef CONFIG_DEBUG_FS
+static int ucd9000_get_mfr_status(struct i2c_client *client, u8 *buffer)
+{
+ int ret = pmbus_set_page(client, 0);
+
+ if (ret < 0)
+ return ret;
+
+ return i2c_smbus_read_block_data(client, UCD9000_MFR_STATUS, buffer);
+}
+
+static int ucd9000_debugfs_show_mfr_status_bit(void *data, u64 *val)
+{
+ struct ucd9000_debugfs_entry *entry = data;
+ struct i2c_client *client = entry->client;
+ u8 buffer[I2C_SMBUS_BLOCK_MAX];
+ int ret;
+
+ ret = ucd9000_get_mfr_status(client, buffer);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Attribute only created for devices with gpi fault bits at bits
+ * 16-23, which is the second byte of the response.
+ */
+ *val = !!(buffer[1] & BIT(entry->index));
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(ucd9000_debugfs_mfr_status_bit,
+ ucd9000_debugfs_show_mfr_status_bit, NULL, "%1lld\n");
+
+static ssize_t ucd9000_debugfs_read_mfr_status(struct file *file,
+ char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct i2c_client *client = file->private_data;
+ u8 buffer[I2C_SMBUS_BLOCK_MAX];
+ char str[(I2C_SMBUS_BLOCK_MAX * 2) + 2];
+ char *res;
+ int rc;
+
+ rc = ucd9000_get_mfr_status(client, buffer);
+ if (rc < 0)
+ return rc;
+
+ res = bin2hex(str, buffer, min(rc, I2C_SMBUS_BLOCK_MAX));
+ *res++ = '\n';
+ *res = 0;
+
+ return simple_read_from_buffer(buf, count, ppos, str, res - str);
+}
+
+static const struct file_operations ucd9000_debugfs_show_mfr_status_fops = {
+ .llseek = noop_llseek,
+ .read = ucd9000_debugfs_read_mfr_status,
+ .open = simple_open,
+};
+
+static int ucd9000_init_debugfs(struct i2c_client *client,
+ const struct i2c_device_id *mid,
+ struct ucd9000_data *data)
+{
+ struct dentry *debugfs;
+ struct ucd9000_debugfs_entry *entries;
+ int i;
+ char name[UCD9000_DEBUGFS_NAME_LEN];
+
+ debugfs = pmbus_get_debugfs_dir(client);
+ if (!debugfs)
+ return -ENOENT;
+
+ data->debugfs = debugfs_create_dir(client->name, debugfs);
+ if (!data->debugfs)
+ return -ENOENT;
+
+ /*
+ * Of the chips this driver supports, only the UCD9090, UCD90160,
+ * and UCD90910 report GPI faults in their MFR_STATUS register, so only
+ * create the GPI fault debugfs attributes for those chips.
+ */
+ if (mid->driver_data == ucd9090 || mid->driver_data == ucd90160 ||
+ mid->driver_data == ucd90910) {
+ entries = devm_kzalloc(&client->dev,
+ sizeof(*entries) * UCD9000_GPI_COUNT,
+ GFP_KERNEL);
+ if (!entries)
+ return -ENOMEM;
+
+ for (i = 0; i < UCD9000_GPI_COUNT; i++) {
+ entries[i].client = client;
+ entries[i].index = i;
+ scnprintf(name, UCD9000_DEBUGFS_NAME_LEN,
+ "gpi%d_alarm", i + 1);
+ debugfs_create_file(name, 0444, data->debugfs,
+ &entries[i],
+ &ucd9000_debugfs_mfr_status_bit);
+ }
+ }
+
+ scnprintf(name, UCD9000_DEBUGFS_NAME_LEN, "mfr_status");
+ debugfs_create_file(name, 0444, data->debugfs, client,
+ &ucd9000_debugfs_show_mfr_status_fops);
+
+ return 0;
+}
+#else
+static int ucd9000_init_debugfs(struct i2c_client *client,
+ const struct i2c_device_id *mid,
+ struct ucd9000_data *data)
+{
+ return 0;
+}
+#endif /* CONFIG_DEBUG_FS */
+
static int ucd9000_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -263,7 +600,18 @@ static int ucd9000_probe(struct i2c_client *client,
| PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34;
}
- return pmbus_do_probe(client, mid, info);
+ ucd9000_probe_gpio(client, mid, data);
+
+ ret = pmbus_do_probe(client, mid, info);
+ if (ret)
+ return ret;
+
+ ret = ucd9000_init_debugfs(client, mid, data);
+ if (ret)
+ dev_warn(&client->dev, "Failed to register debugfs: %d\n",
+ ret);
+
+ return 0;
}
/* This is the driver that will be inserted */
diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c
index 190e7b39ce32..2c7ba70921f5 100644
--- a/drivers/hwmon/sht21.c
+++ b/drivers/hwmon/sht21.c
@@ -16,8 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
*
- * Data sheet available (5/2010) at
- * http://www.sensirion.com/en/pdf/product_information/Datasheet-humidity-sensor-SHT21.pdf
+ * Data sheet available at http://www.sensirion.com/file/datasheet_sht21
*/
#include <linux/module.h>
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
index 07a0cb0a1f28..0e81f287d305 100644
--- a/drivers/hwmon/via-cputemp.c
+++ b/drivers/hwmon/via-cputemp.c
@@ -136,20 +136,24 @@ static int via_cputemp_probe(struct platform_device *pdev)
data->id = pdev->id;
data->name = "via_cputemp";
- switch (c->x86_model) {
- case 0xA:
- /* C7 A */
- case 0xD:
- /* C7 D */
- data->msr_temp = 0x1169;
- data->msr_vid = 0x198;
- break;
- case 0xF:
- /* Nano */
+ if (c->x86 == 7) {
data->msr_temp = 0x1423;
- break;
- default:
- return -ENODEV;
+ } else {
+ switch (c->x86_model) {
+ case 0xA:
+ /* C7 A */
+ case 0xD:
+ /* C7 D */
+ data->msr_temp = 0x1169;
+ data->msr_vid = 0x198;
+ break;
+ case 0xF:
+ /* Nano */
+ data->msr_temp = 0x1423;
+ break;
+ default:
+ return -ENODEV;
+ }
}
/* test if we can access the TEMPERATURE MSR */
@@ -283,6 +287,7 @@ static const struct x86_cpu_id __initconst cputemp_ids[] = {
{ X86_VENDOR_CENTAUR, 6, 0xa, }, /* C7 A */
{ X86_VENDOR_CENTAUR, 6, 0xd, }, /* C7 D */
{ X86_VENDOR_CENTAUR, 6, 0xf, }, /* Nano */
+ { X86_VENDOR_CENTAUR, 7, X86_MODEL_ANY, },
{}
};
MODULE_DEVICE_TABLE(x86cpu, cputemp_ids);
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 83819d0cbf90..2a99f0f14795 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -81,11 +81,12 @@
*/
#define AMD_IOMMU_PGSIZES ((~0xFFFUL) & ~(2ULL << 38))
-static DEFINE_RWLOCK(amd_iommu_devtable_lock);
+static DEFINE_SPINLOCK(amd_iommu_devtable_lock);
+static DEFINE_SPINLOCK(pd_bitmap_lock);
+static DEFINE_SPINLOCK(iommu_table_lock);
/* List of all available dev_data structures */
-static LIST_HEAD(dev_data_list);
-static DEFINE_SPINLOCK(dev_data_list_lock);
+static LLIST_HEAD(dev_data_list);
LIST_HEAD(ioapic_map);
LIST_HEAD(hpet_map);
@@ -204,40 +205,33 @@ static struct dma_ops_domain* to_dma_ops_domain(struct protection_domain *domain
static struct iommu_dev_data *alloc_dev_data(u16 devid)
{
struct iommu_dev_data *dev_data;
- unsigned long flags;
dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL);
if (!dev_data)
return NULL;
dev_data->devid = devid;
-
- spin_lock_irqsave(&dev_data_list_lock, flags);
- list_add_tail(&dev_data->dev_data_list, &dev_data_list);
- spin_unlock_irqrestore(&dev_data_list_lock, flags);
-
ratelimit_default_init(&dev_data->rs);
+ llist_add(&dev_data->dev_data_list, &dev_data_list);
return dev_data;
}
static struct iommu_dev_data *search_dev_data(u16 devid)
{
struct iommu_dev_data *dev_data;
- unsigned long flags;
+ struct llist_node *node;
- spin_lock_irqsave(&dev_data_list_lock, flags);
- list_for_each_entry(dev_data, &dev_data_list, dev_data_list) {
+ if (llist_empty(&dev_data_list))
+ return NULL;
+
+ node = dev_data_list.first;
+ llist_for_each_entry(dev_data, node, dev_data_list) {
if (dev_data->devid == devid)
- goto out_unlock;
+ return dev_data;
}
- dev_data = NULL;
-
-out_unlock:
- spin_unlock_irqrestore(&dev_data_list_lock, flags);
-
- return dev_data;
+ return NULL;
}
static int __last_alias(struct pci_dev *pdev, u16 alias, void *data)
@@ -311,6 +305,8 @@ static struct iommu_dev_data *find_dev_data(u16 devid)
if (dev_data == NULL) {
dev_data = alloc_dev_data(devid);
+ if (!dev_data)
+ return NULL;
if (translation_pre_enabled(iommu))
dev_data->defer_attach = true;
@@ -548,6 +544,7 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id,
static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
{
+ struct device *dev = iommu->iommu.dev;
int type, devid, domid, flags;
volatile u32 *event = __evt;
int count = 0;
@@ -574,53 +571,53 @@ retry:
amd_iommu_report_page_fault(devid, domid, address, flags);
return;
} else {
- printk(KERN_ERR "AMD-Vi: Event logged [");
+ dev_err(dev, "AMD-Vi: Event logged [");
}
switch (type) {
case EVENT_TYPE_ILL_DEV:
- printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x "
- "address=0x%016llx flags=0x%04x]\n",
- PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
- address, flags);
+ dev_err(dev, "ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x "
+ "address=0x%016llx flags=0x%04x]\n",
+ PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ address, flags);
dump_dte_entry(devid);
break;
case EVENT_TYPE_DEV_TAB_ERR:
- printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
- "address=0x%016llx flags=0x%04x]\n",
- PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
- address, flags);
+ dev_err(dev, "DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
+ "address=0x%016llx flags=0x%04x]\n",
+ PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ address, flags);
break;
case EVENT_TYPE_PAGE_TAB_ERR:
- printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
- "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
- PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
- domid, address, flags);
+ dev_err(dev, "PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
+ "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
+ PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ domid, address, flags);
break;
case EVENT_TYPE_ILL_CMD:
- printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
+ dev_err(dev, "ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
dump_command(address);
break;
case EVENT_TYPE_CMD_HARD_ERR:
- printk("COMMAND_HARDWARE_ERROR address=0x%016llx "
- "flags=0x%04x]\n", address, flags);
+ dev_err(dev, "COMMAND_HARDWARE_ERROR address=0x%016llx "
+ "flags=0x%04x]\n", address, flags);
break;
case EVENT_TYPE_IOTLB_INV_TO:
- printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x "
- "address=0x%016llx]\n",
- PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
- address);
+ dev_err(dev, "IOTLB_INV_TIMEOUT device=%02x:%02x.%x "
+ "address=0x%016llx]\n",
+ PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ address);
break;
case EVENT_TYPE_INV_DEV_REQ:
- printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x "
- "address=0x%016llx flags=0x%04x]\n",
- PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
- address, flags);
+ dev_err(dev, "INVALID_DEVICE_REQUEST device=%02x:%02x.%x "
+ "address=0x%016llx flags=0x%04x]\n",
+ PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ address, flags);
break;
default:
- printk(KERN_ERR "UNKNOWN type=0x%02x event[0]=0x%08x "
- "event[1]=0x%08x event[2]=0x%08x event[3]=0x%08x\n",
- type, event[0], event[1], event[2], event[3]);
+ dev_err(dev, KERN_ERR "UNKNOWN event[0]=0x%08x event[1]=0x%08x "
+ "event[2]=0x%08x event[3]=0x%08x\n",
+ event[0], event[1], event[2], event[3]);
}
memset(__evt, 0, 4 * sizeof(u32));
@@ -1057,9 +1054,9 @@ static int iommu_queue_command_sync(struct amd_iommu *iommu,
unsigned long flags;
int ret;
- spin_lock_irqsave(&iommu->lock, flags);
+ raw_spin_lock_irqsave(&iommu->lock, flags);
ret = __iommu_queue_command_sync(iommu, cmd, sync);
- spin_unlock_irqrestore(&iommu->lock, flags);
+ raw_spin_unlock_irqrestore(&iommu->lock, flags);
return ret;
}
@@ -1085,7 +1082,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
build_completion_wait(&cmd, (u64)&iommu->cmd_sem);
- spin_lock_irqsave(&iommu->lock, flags);
+ raw_spin_lock_irqsave(&iommu->lock, flags);
iommu->cmd_sem = 0;
@@ -1096,7 +1093,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
ret = wait_on_sem(&iommu->cmd_sem);
out_unlock:
- spin_unlock_irqrestore(&iommu->lock, flags);
+ raw_spin_unlock_irqrestore(&iommu->lock, flags);
return ret;
}
@@ -1606,29 +1603,26 @@ static void del_domain_from_list(struct protection_domain *domain)
static u16 domain_id_alloc(void)
{
- unsigned long flags;
int id;
- write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+ spin_lock(&pd_bitmap_lock);
id = find_first_zero_bit(amd_iommu_pd_alloc_bitmap, MAX_DOMAIN_ID);
BUG_ON(id == 0);
if (id > 0 && id < MAX_DOMAIN_ID)
__set_bit(id, amd_iommu_pd_alloc_bitmap);
else
id = 0;
- write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+ spin_unlock(&pd_bitmap_lock);
return id;
}
static void domain_id_free(int id)
{
- unsigned long flags;
-
- write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+ spin_lock(&pd_bitmap_lock);
if (id > 0 && id < MAX_DOMAIN_ID)
__clear_bit(id, amd_iommu_pd_alloc_bitmap);
- write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+ spin_unlock(&pd_bitmap_lock);
}
#define DEFINE_FREE_PT_FN(LVL, FN) \
@@ -2104,9 +2098,9 @@ static int attach_device(struct device *dev,
}
skip_ats_check:
- write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+ spin_lock_irqsave(&amd_iommu_devtable_lock, flags);
ret = __attach_device(dev_data, domain);
- write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+ spin_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
/*
* We might boot into a crash-kernel here. The crashed kernel
@@ -2156,9 +2150,9 @@ static void detach_device(struct device *dev)
domain = dev_data->domain;
/* lock device table */
- write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+ spin_lock_irqsave(&amd_iommu_devtable_lock, flags);
__detach_device(dev_data);
- write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+ spin_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
if (!dev_is_pci(dev))
return;
@@ -2795,7 +2789,7 @@ static void cleanup_domain(struct protection_domain *domain)
struct iommu_dev_data *entry;
unsigned long flags;
- write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+ spin_lock_irqsave(&amd_iommu_devtable_lock, flags);
while (!list_empty(&domain->dev_list)) {
entry = list_first_entry(&domain->dev_list,
@@ -2803,7 +2797,7 @@ static void cleanup_domain(struct protection_domain *domain)
__detach_device(entry);
}
- write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+ spin_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
}
static void protection_domain_free(struct protection_domain *domain)
@@ -3025,15 +3019,12 @@ static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
size_t unmap_size;
if (domain->mode == PAGE_MODE_NONE)
- return -EINVAL;
+ return 0;
mutex_lock(&domain->api_lock);
unmap_size = iommu_unmap_page(domain, iova, page_size);
mutex_unlock(&domain->api_lock);
- domain_flush_tlb_pde(domain);
- domain_flush_complete(domain);
-
return unmap_size;
}
@@ -3151,6 +3142,19 @@ static bool amd_iommu_is_attach_deferred(struct iommu_domain *domain,
return dev_data->defer_attach;
}
+static void amd_iommu_flush_iotlb_all(struct iommu_domain *domain)
+{
+ struct protection_domain *dom = to_pdomain(domain);
+
+ domain_flush_tlb_pde(dom);
+ domain_flush_complete(dom);
+}
+
+static void amd_iommu_iotlb_range_add(struct iommu_domain *domain,
+ unsigned long iova, size_t size)
+{
+}
+
const struct iommu_ops amd_iommu_ops = {
.capable = amd_iommu_capable,
.domain_alloc = amd_iommu_domain_alloc,
@@ -3169,6 +3173,9 @@ const struct iommu_ops amd_iommu_ops = {
.apply_resv_region = amd_iommu_apply_resv_region,
.is_attach_deferred = amd_iommu_is_attach_deferred,
.pgsize_bitmap = AMD_IOMMU_PGSIZES,
+ .flush_iotlb_all = amd_iommu_flush_iotlb_all,
+ .iotlb_range_add = amd_iommu_iotlb_range_add,
+ .iotlb_sync = amd_iommu_flush_iotlb_all,
};
/*****************************************************************************
@@ -3570,14 +3577,62 @@ static void set_dte_irq_entry(u16 devid, struct irq_remap_table *table)
amd_iommu_dev_table[devid].data[2] = dte;
}
-static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic)
+static struct irq_remap_table *get_irq_table(u16 devid)
+{
+ struct irq_remap_table *table;
+
+ if (WARN_ONCE(!amd_iommu_rlookup_table[devid],
+ "%s: no iommu for devid %x\n", __func__, devid))
+ return NULL;
+
+ table = irq_lookup_table[devid];
+ if (WARN_ONCE(!table, "%s: no table for devid %x\n", __func__, devid))
+ return NULL;
+
+ return table;
+}
+
+static struct irq_remap_table *__alloc_irq_table(void)
+{
+ struct irq_remap_table *table;
+
+ table = kzalloc(sizeof(*table), GFP_KERNEL);
+ if (!table)
+ return NULL;
+
+ table->table = kmem_cache_alloc(amd_iommu_irq_cache, GFP_KERNEL);
+ if (!table->table) {
+ kfree(table);
+ return NULL;
+ }
+ raw_spin_lock_init(&table->lock);
+
+ if (!AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir))
+ memset(table->table, 0,
+ MAX_IRQS_PER_TABLE * sizeof(u32));
+ else
+ memset(table->table, 0,
+ (MAX_IRQS_PER_TABLE * (sizeof(u64) * 2)));
+ return table;
+}
+
+static void set_remap_table_entry(struct amd_iommu *iommu, u16 devid,
+ struct irq_remap_table *table)
+{
+ irq_lookup_table[devid] = table;
+ set_dte_irq_entry(devid, table);
+ iommu_flush_dte(iommu, devid);
+}
+
+static struct irq_remap_table *alloc_irq_table(u16 devid)
{
struct irq_remap_table *table = NULL;
+ struct irq_remap_table *new_table = NULL;
struct amd_iommu *iommu;
unsigned long flags;
u16 alias;
- write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+ spin_lock_irqsave(&iommu_table_lock, flags);
iommu = amd_iommu_rlookup_table[devid];
if (!iommu)
@@ -3590,60 +3645,45 @@ static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic)
alias = amd_iommu_alias_table[devid];
table = irq_lookup_table[alias];
if (table) {
- irq_lookup_table[devid] = table;
- set_dte_irq_entry(devid, table);
- iommu_flush_dte(iommu, devid);
- goto out;
+ set_remap_table_entry(iommu, devid, table);
+ goto out_wait;
}
+ spin_unlock_irqrestore(&iommu_table_lock, flags);
/* Nothing there yet, allocate new irq remapping table */
- table = kzalloc(sizeof(*table), GFP_ATOMIC);
- if (!table)
- goto out_unlock;
-
- /* Initialize table spin-lock */
- spin_lock_init(&table->lock);
+ new_table = __alloc_irq_table();
+ if (!new_table)
+ return NULL;
- if (ioapic)
- /* Keep the first 32 indexes free for IOAPIC interrupts */
- table->min_index = 32;
+ spin_lock_irqsave(&iommu_table_lock, flags);
- table->table = kmem_cache_alloc(amd_iommu_irq_cache, GFP_ATOMIC);
- if (!table->table) {
- kfree(table);
- table = NULL;
+ table = irq_lookup_table[devid];
+ if (table)
goto out_unlock;
- }
- if (!AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir))
- memset(table->table, 0,
- MAX_IRQS_PER_TABLE * sizeof(u32));
- else
- memset(table->table, 0,
- (MAX_IRQS_PER_TABLE * (sizeof(u64) * 2)));
-
- if (ioapic) {
- int i;
-
- for (i = 0; i < 32; ++i)
- iommu->irte_ops->set_allocated(table, i);
+ table = irq_lookup_table[alias];
+ if (table) {
+ set_remap_table_entry(iommu, devid, table);
+ goto out_wait;
}
- irq_lookup_table[devid] = table;
- set_dte_irq_entry(devid, table);
- iommu_flush_dte(iommu, devid);
- if (devid != alias) {
- irq_lookup_table[alias] = table;
- set_dte_irq_entry(alias, table);
- iommu_flush_dte(iommu, alias);
- }
+ table = new_table;
+ new_table = NULL;
-out:
+ set_remap_table_entry(iommu, devid, table);
+ if (devid != alias)
+ set_remap_table_entry(iommu, alias, table);
+
+out_wait:
iommu_completion_wait(iommu);
out_unlock:
- write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+ spin_unlock_irqrestore(&iommu_table_lock, flags);
+ if (new_table) {
+ kmem_cache_free(amd_iommu_irq_cache, new_table->table);
+ kfree(new_table);
+ }
return table;
}
@@ -3657,14 +3697,14 @@ static int alloc_irq_index(u16 devid, int count, bool align)
if (!iommu)
return -ENODEV;
- table = get_irq_table(devid, false);
+ table = alloc_irq_table(devid);
if (!table)
return -ENODEV;
if (align)
alignment = roundup_pow_of_two(count);
- spin_lock_irqsave(&table->lock, flags);
+ raw_spin_lock_irqsave(&table->lock, flags);
/* Scan table for free entries */
for (index = ALIGN(table->min_index, alignment), c = 0;
@@ -3691,7 +3731,7 @@ static int alloc_irq_index(u16 devid, int count, bool align)
index = -ENOSPC;
out:
- spin_unlock_irqrestore(&table->lock, flags);
+ raw_spin_unlock_irqrestore(&table->lock, flags);
return index;
}
@@ -3708,11 +3748,11 @@ static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte,
if (iommu == NULL)
return -EINVAL;
- table = get_irq_table(devid, false);
+ table = get_irq_table(devid);
if (!table)
return -ENOMEM;
- spin_lock_irqsave(&table->lock, flags);
+ raw_spin_lock_irqsave(&table->lock, flags);
entry = (struct irte_ga *)table->table;
entry = &entry[index];
@@ -3723,7 +3763,7 @@ static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte,
if (data)
data->ref = entry;
- spin_unlock_irqrestore(&table->lock, flags);
+ raw_spin_unlock_irqrestore(&table->lock, flags);
iommu_flush_irt(iommu, devid);
iommu_completion_wait(iommu);
@@ -3741,13 +3781,13 @@ static int modify_irte(u16 devid, int index, union irte *irte)
if (iommu == NULL)
return -EINVAL;
- table = get_irq_table(devid, false);
+ table = get_irq_table(devid);
if (!table)
return -ENOMEM;
- spin_lock_irqsave(&table->lock, flags);
+ raw_spin_lock_irqsave(&table->lock, flags);
table->table[index] = irte->val;
- spin_unlock_irqrestore(&table->lock, flags);
+ raw_spin_unlock_irqrestore(&table->lock, flags);
iommu_flush_irt(iommu, devid);
iommu_completion_wait(iommu);
@@ -3765,13 +3805,13 @@ static void free_irte(u16 devid, int index)
if (iommu == NULL)
return;
- table = get_irq_table(devid, false);
+ table = get_irq_table(devid);
if (!table)
return;
- spin_lock_irqsave(&table->lock, flags);
+ raw_spin_lock_irqsave(&table->lock, flags);
iommu->irte_ops->clear_allocated(table, index);
- spin_unlock_irqrestore(&table->lock, flags);
+ raw_spin_unlock_irqrestore(&table->lock, flags);
iommu_flush_irt(iommu, devid);
iommu_completion_wait(iommu);
@@ -3852,10 +3892,8 @@ static void irte_ga_set_affinity(void *entry, u16 devid, u16 index,
u8 vector, u32 dest_apicid)
{
struct irte_ga *irte = (struct irte_ga *) entry;
- struct iommu_dev_data *dev_data = search_dev_data(devid);
- if (!dev_data || !dev_data->use_vapic ||
- !irte->lo.fields_remap.guest_mode) {
+ if (!irte->lo.fields_remap.guest_mode) {
irte->hi.fields.vector = vector;
irte->lo.fields_remap.destination = dest_apicid;
modify_irte_ga(devid, index, irte, NULL);
@@ -4061,7 +4099,7 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
struct amd_ir_data *data = NULL;
struct irq_cfg *cfg;
int i, ret, devid;
- int index = -1;
+ int index;
if (!info)
return -EINVAL;
@@ -4085,10 +4123,26 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
return ret;
if (info->type == X86_IRQ_ALLOC_TYPE_IOAPIC) {
- if (get_irq_table(devid, true))
+ struct irq_remap_table *table;
+ struct amd_iommu *iommu;
+
+ table = alloc_irq_table(devid);
+ if (table) {
+ if (!table->min_index) {
+ /*
+ * Keep the first 32 indexes free for IOAPIC
+ * interrupts.
+ */
+ table->min_index = 32;
+ iommu = amd_iommu_rlookup_table[devid];
+ for (i = 0; i < 32; ++i)
+ iommu->irte_ops->set_allocated(table, i);
+ }
+ WARN_ON(table->min_index != 32);
index = info->ioapic_pin;
- else
- ret = -ENOMEM;
+ } else {
+ index = -ENOMEM;
+ }
} else {
bool align = (info->type == X86_IRQ_ALLOC_TYPE_MSI);
@@ -4354,7 +4408,7 @@ int amd_iommu_update_ga(int cpu, bool is_run, void *data)
{
unsigned long flags;
struct amd_iommu *iommu;
- struct irq_remap_table *irt;
+ struct irq_remap_table *table;
struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
int devid = ir_data->irq_2_irte.devid;
struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
@@ -4368,11 +4422,11 @@ int amd_iommu_update_ga(int cpu, bool is_run, void *data)
if (!iommu)
return -ENODEV;
- irt = get_irq_table(devid, false);
- if (!irt)
+ table = get_irq_table(devid);
+ if (!table)
return -ENODEV;
- spin_lock_irqsave(&irt->lock, flags);
+ raw_spin_lock_irqsave(&table->lock, flags);
if (ref->lo.fields_vapic.guest_mode) {
if (cpu >= 0)
@@ -4381,7 +4435,7 @@ int amd_iommu_update_ga(int cpu, bool is_run, void *data)
barrier();
}
- spin_unlock_irqrestore(&irt->lock, flags);
+ raw_spin_unlock_irqrestore(&table->lock, flags);
iommu_flush_irt(iommu, devid);
iommu_completion_wait(iommu);
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 4e4a615bf13f..904c575d1677 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -1474,7 +1474,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
{
int ret;
- spin_lock_init(&iommu->lock);
+ raw_spin_lock_init(&iommu->lock);
/* Add IOMMU to internal data structures */
list_add_tail(&iommu->list, &amd_iommu_list);
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 6a877ebd058b..1c9b080276c9 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -408,7 +408,7 @@ extern bool amd_iommu_iotlb_sup;
#define IRQ_TABLE_ALIGNMENT 128
struct irq_remap_table {
- spinlock_t lock;
+ raw_spinlock_t lock;
unsigned min_index;
u32 *table;
};
@@ -490,7 +490,7 @@ struct amd_iommu {
int index;
/* locks the accesses to the hardware */
- spinlock_t lock;
+ raw_spinlock_t lock;
/* Pointer to PCI device of this IOMMU */
struct pci_dev *dev;
@@ -627,7 +627,7 @@ struct devid_map {
*/
struct iommu_dev_data {
struct list_head list; /* For domain->dev_list */
- struct list_head dev_data_list; /* For global dev_data_list */
+ struct llist_node dev_data_list; /* For global dev_data_list */
struct protection_domain *domain; /* Domain the device is bound to */
u16 devid; /* PCI Device ID */
u16 alias; /* Alias Device ID */
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 3f2f1fc68b52..1d647104bccc 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -22,6 +22,8 @@
#include <linux/acpi.h>
#include <linux/acpi_iort.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/dma-iommu.h>
#include <linux/err.h>
@@ -43,18 +45,15 @@
/* MMIO registers */
#define ARM_SMMU_IDR0 0x0
-#define IDR0_ST_LVL_SHIFT 27
-#define IDR0_ST_LVL_MASK 0x3
-#define IDR0_ST_LVL_2LVL (1 << IDR0_ST_LVL_SHIFT)
-#define IDR0_STALL_MODEL_SHIFT 24
-#define IDR0_STALL_MODEL_MASK 0x3
-#define IDR0_STALL_MODEL_STALL (0 << IDR0_STALL_MODEL_SHIFT)
-#define IDR0_STALL_MODEL_FORCE (2 << IDR0_STALL_MODEL_SHIFT)
-#define IDR0_TTENDIAN_SHIFT 21
-#define IDR0_TTENDIAN_MASK 0x3
-#define IDR0_TTENDIAN_LE (2 << IDR0_TTENDIAN_SHIFT)
-#define IDR0_TTENDIAN_BE (3 << IDR0_TTENDIAN_SHIFT)
-#define IDR0_TTENDIAN_MIXED (0 << IDR0_TTENDIAN_SHIFT)
+#define IDR0_ST_LVL GENMASK(28, 27)
+#define IDR0_ST_LVL_2LVL 1
+#define IDR0_STALL_MODEL GENMASK(25, 24)
+#define IDR0_STALL_MODEL_STALL 0
+#define IDR0_STALL_MODEL_FORCE 2
+#define IDR0_TTENDIAN GENMASK(22, 21)
+#define IDR0_TTENDIAN_MIXED 0
+#define IDR0_TTENDIAN_LE 2
+#define IDR0_TTENDIAN_BE 3
#define IDR0_CD2L (1 << 19)
#define IDR0_VMID16 (1 << 18)
#define IDR0_PRI (1 << 16)
@@ -64,10 +63,9 @@
#define IDR0_ATS (1 << 10)
#define IDR0_HYP (1 << 9)
#define IDR0_COHACC (1 << 4)
-#define IDR0_TTF_SHIFT 2
-#define IDR0_TTF_MASK 0x3
-#define IDR0_TTF_AARCH64 (2 << IDR0_TTF_SHIFT)
-#define IDR0_TTF_AARCH32_64 (3 << IDR0_TTF_SHIFT)
+#define IDR0_TTF GENMASK(3, 2)
+#define IDR0_TTF_AARCH64 2
+#define IDR0_TTF_AARCH32_64 3
#define IDR0_S1P (1 << 1)
#define IDR0_S2P (1 << 0)
@@ -75,31 +73,27 @@
#define IDR1_TABLES_PRESET (1 << 30)
#define IDR1_QUEUES_PRESET (1 << 29)
#define IDR1_REL (1 << 28)
-#define IDR1_CMDQ_SHIFT 21
-#define IDR1_CMDQ_MASK 0x1f
-#define IDR1_EVTQ_SHIFT 16
-#define IDR1_EVTQ_MASK 0x1f
-#define IDR1_PRIQ_SHIFT 11
-#define IDR1_PRIQ_MASK 0x1f
-#define IDR1_SSID_SHIFT 6
-#define IDR1_SSID_MASK 0x1f
-#define IDR1_SID_SHIFT 0
-#define IDR1_SID_MASK 0x3f
+#define IDR1_CMDQS GENMASK(25, 21)
+#define IDR1_EVTQS GENMASK(20, 16)
+#define IDR1_PRIQS GENMASK(15, 11)
+#define IDR1_SSIDSIZE GENMASK(10, 6)
+#define IDR1_SIDSIZE GENMASK(5, 0)
#define ARM_SMMU_IDR5 0x14
-#define IDR5_STALL_MAX_SHIFT 16
-#define IDR5_STALL_MAX_MASK 0xffff
+#define IDR5_STALL_MAX GENMASK(31, 16)
#define IDR5_GRAN64K (1 << 6)
#define IDR5_GRAN16K (1 << 5)
#define IDR5_GRAN4K (1 << 4)
-#define IDR5_OAS_SHIFT 0
-#define IDR5_OAS_MASK 0x7
-#define IDR5_OAS_32_BIT (0 << IDR5_OAS_SHIFT)
-#define IDR5_OAS_36_BIT (1 << IDR5_OAS_SHIFT)
-#define IDR5_OAS_40_BIT (2 << IDR5_OAS_SHIFT)
-#define IDR5_OAS_42_BIT (3 << IDR5_OAS_SHIFT)
-#define IDR5_OAS_44_BIT (4 << IDR5_OAS_SHIFT)
-#define IDR5_OAS_48_BIT (5 << IDR5_OAS_SHIFT)
+#define IDR5_OAS GENMASK(2, 0)
+#define IDR5_OAS_32_BIT 0
+#define IDR5_OAS_36_BIT 1
+#define IDR5_OAS_40_BIT 2
+#define IDR5_OAS_42_BIT 3
+#define IDR5_OAS_44_BIT 4
+#define IDR5_OAS_48_BIT 5
+#define IDR5_OAS_52_BIT 6
+#define IDR5_VAX GENMASK(11, 10)
+#define IDR5_VAX_52_BIT 1
#define ARM_SMMU_CR0 0x20
#define CR0_CMDQEN (1 << 3)
@@ -110,18 +104,16 @@
#define ARM_SMMU_CR0ACK 0x24
#define ARM_SMMU_CR1 0x28
-#define CR1_SH_NSH 0
-#define CR1_SH_OSH 2
-#define CR1_SH_ISH 3
+#define CR1_TABLE_SH GENMASK(11, 10)
+#define CR1_TABLE_OC GENMASK(9, 8)
+#define CR1_TABLE_IC GENMASK(7, 6)
+#define CR1_QUEUE_SH GENMASK(5, 4)
+#define CR1_QUEUE_OC GENMASK(3, 2)
+#define CR1_QUEUE_IC GENMASK(1, 0)
+/* CR1 cacheability fields don't quite follow the usual TCR-style encoding */
#define CR1_CACHE_NC 0
#define CR1_CACHE_WB 1
#define CR1_CACHE_WT 2
-#define CR1_TABLE_SH_SHIFT 10
-#define CR1_TABLE_OC_SHIFT 8
-#define CR1_TABLE_IC_SHIFT 6
-#define CR1_QUEUE_SH_SHIFT 4
-#define CR1_QUEUE_OC_SHIFT 2
-#define CR1_QUEUE_IC_SHIFT 0
#define ARM_SMMU_CR2 0x2c
#define CR2_PTM (1 << 2)
@@ -129,8 +121,8 @@
#define CR2_E2H (1 << 0)
#define ARM_SMMU_GBPA 0x44
-#define GBPA_ABORT (1 << 20)
#define GBPA_UPDATE (1 << 31)
+#define GBPA_ABORT (1 << 20)
#define ARM_SMMU_IRQ_CTRL 0x50
#define IRQ_CTRL_EVTQ_IRQEN (1 << 2)
@@ -158,18 +150,14 @@
#define ARM_SMMU_STRTAB_BASE 0x80
#define STRTAB_BASE_RA (1UL << 62)
-#define STRTAB_BASE_ADDR_SHIFT 6
-#define STRTAB_BASE_ADDR_MASK 0x3ffffffffffUL
+#define STRTAB_BASE_ADDR_MASK GENMASK_ULL(51, 6)
#define ARM_SMMU_STRTAB_BASE_CFG 0x88
-#define STRTAB_BASE_CFG_LOG2SIZE_SHIFT 0
-#define STRTAB_BASE_CFG_LOG2SIZE_MASK 0x3f
-#define STRTAB_BASE_CFG_SPLIT_SHIFT 6
-#define STRTAB_BASE_CFG_SPLIT_MASK 0x1f
-#define STRTAB_BASE_CFG_FMT_SHIFT 16
-#define STRTAB_BASE_CFG_FMT_MASK 0x3
-#define STRTAB_BASE_CFG_FMT_LINEAR (0 << STRTAB_BASE_CFG_FMT_SHIFT)
-#define STRTAB_BASE_CFG_FMT_2LVL (1 << STRTAB_BASE_CFG_FMT_SHIFT)
+#define STRTAB_BASE_CFG_FMT GENMASK(17, 16)
+#define STRTAB_BASE_CFG_FMT_LINEAR 0
+#define STRTAB_BASE_CFG_FMT_2LVL 1
+#define STRTAB_BASE_CFG_SPLIT GENMASK(10, 6)
+#define STRTAB_BASE_CFG_LOG2SIZE GENMASK(5, 0)
#define ARM_SMMU_CMDQ_BASE 0x90
#define ARM_SMMU_CMDQ_PROD 0x98
@@ -190,14 +178,16 @@
#define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc
/* Common MSI config fields */
-#define MSI_CFG0_ADDR_SHIFT 2
-#define MSI_CFG0_ADDR_MASK 0x3fffffffffffUL
-#define MSI_CFG2_SH_SHIFT 4
-#define MSI_CFG2_SH_NSH (0UL << MSI_CFG2_SH_SHIFT)
-#define MSI_CFG2_SH_OSH (2UL << MSI_CFG2_SH_SHIFT)
-#define MSI_CFG2_SH_ISH (3UL << MSI_CFG2_SH_SHIFT)
-#define MSI_CFG2_MEMATTR_SHIFT 0
-#define MSI_CFG2_MEMATTR_DEVICE_nGnRE (0x1 << MSI_CFG2_MEMATTR_SHIFT)
+#define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2)
+#define MSI_CFG2_SH GENMASK(5, 4)
+#define MSI_CFG2_MEMATTR GENMASK(3, 0)
+
+/* Common memory attribute values */
+#define ARM_SMMU_SH_NSH 0
+#define ARM_SMMU_SH_OSH 2
+#define ARM_SMMU_SH_ISH 3
+#define ARM_SMMU_MEMATTR_DEVICE_nGnRE 0x1
+#define ARM_SMMU_MEMATTR_OIWB 0xf
#define Q_IDX(q, p) ((p) & ((1 << (q)->max_n_shift) - 1))
#define Q_WRP(q, p) ((p) & (1 << (q)->max_n_shift))
@@ -207,10 +197,8 @@
Q_IDX(q, p) * (q)->ent_dwords)
#define Q_BASE_RWA (1UL << 62)
-#define Q_BASE_ADDR_SHIFT 5
-#define Q_BASE_ADDR_MASK 0xfffffffffffUL
-#define Q_BASE_LOG2SIZE_SHIFT 0
-#define Q_BASE_LOG2SIZE_MASK 0x1fUL
+#define Q_BASE_ADDR_MASK GENMASK_ULL(51, 5)
+#define Q_BASE_LOG2SIZE GENMASK(4, 0)
/*
* Stream table.
@@ -223,187 +211,143 @@
#define STRTAB_SPLIT 8
#define STRTAB_L1_DESC_DWORDS 1
-#define STRTAB_L1_DESC_SPAN_SHIFT 0
-#define STRTAB_L1_DESC_SPAN_MASK 0x1fUL
-#define STRTAB_L1_DESC_L2PTR_SHIFT 6
-#define STRTAB_L1_DESC_L2PTR_MASK 0x3ffffffffffUL
+#define STRTAB_L1_DESC_SPAN GENMASK_ULL(4, 0)
+#define STRTAB_L1_DESC_L2PTR_MASK GENMASK_ULL(51, 6)
#define STRTAB_STE_DWORDS 8
#define STRTAB_STE_0_V (1UL << 0)
-#define STRTAB_STE_0_CFG_SHIFT 1
-#define STRTAB_STE_0_CFG_MASK 0x7UL
-#define STRTAB_STE_0_CFG_ABORT (0UL << STRTAB_STE_0_CFG_SHIFT)
-#define STRTAB_STE_0_CFG_BYPASS (4UL << STRTAB_STE_0_CFG_SHIFT)
-#define STRTAB_STE_0_CFG_S1_TRANS (5UL << STRTAB_STE_0_CFG_SHIFT)
-#define STRTAB_STE_0_CFG_S2_TRANS (6UL << STRTAB_STE_0_CFG_SHIFT)
-
-#define STRTAB_STE_0_S1FMT_SHIFT 4
-#define STRTAB_STE_0_S1FMT_LINEAR (0UL << STRTAB_STE_0_S1FMT_SHIFT)
-#define STRTAB_STE_0_S1CTXPTR_SHIFT 6
-#define STRTAB_STE_0_S1CTXPTR_MASK 0x3ffffffffffUL
-#define STRTAB_STE_0_S1CDMAX_SHIFT 59
-#define STRTAB_STE_0_S1CDMAX_MASK 0x1fUL
+#define STRTAB_STE_0_CFG GENMASK_ULL(3, 1)
+#define STRTAB_STE_0_CFG_ABORT 0
+#define STRTAB_STE_0_CFG_BYPASS 4
+#define STRTAB_STE_0_CFG_S1_TRANS 5
+#define STRTAB_STE_0_CFG_S2_TRANS 6
+
+#define STRTAB_STE_0_S1FMT GENMASK_ULL(5, 4)
+#define STRTAB_STE_0_S1FMT_LINEAR 0
+#define STRTAB_STE_0_S1CTXPTR_MASK GENMASK_ULL(51, 6)
+#define STRTAB_STE_0_S1CDMAX GENMASK_ULL(63, 59)
#define STRTAB_STE_1_S1C_CACHE_NC 0UL
#define STRTAB_STE_1_S1C_CACHE_WBRA 1UL
#define STRTAB_STE_1_S1C_CACHE_WT 2UL
#define STRTAB_STE_1_S1C_CACHE_WB 3UL
-#define STRTAB_STE_1_S1C_SH_NSH 0UL
-#define STRTAB_STE_1_S1C_SH_OSH 2UL
-#define STRTAB_STE_1_S1C_SH_ISH 3UL
-#define STRTAB_STE_1_S1CIR_SHIFT 2
-#define STRTAB_STE_1_S1COR_SHIFT 4
-#define STRTAB_STE_1_S1CSH_SHIFT 6
+#define STRTAB_STE_1_S1CIR GENMASK_ULL(3, 2)
+#define STRTAB_STE_1_S1COR GENMASK_ULL(5, 4)
+#define STRTAB_STE_1_S1CSH GENMASK_ULL(7, 6)
#define STRTAB_STE_1_S1STALLD (1UL << 27)
+#define STRTAB_STE_1_EATS GENMASK_ULL(29, 28)
#define STRTAB_STE_1_EATS_ABT 0UL
#define STRTAB_STE_1_EATS_TRANS 1UL
#define STRTAB_STE_1_EATS_S1CHK 2UL
-#define STRTAB_STE_1_EATS_SHIFT 28
+#define STRTAB_STE_1_STRW GENMASK_ULL(31, 30)
#define STRTAB_STE_1_STRW_NSEL1 0UL
#define STRTAB_STE_1_STRW_EL2 2UL
-#define STRTAB_STE_1_STRW_SHIFT 30
+#define STRTAB_STE_1_SHCFG GENMASK_ULL(45, 44)
#define STRTAB_STE_1_SHCFG_INCOMING 1UL
-#define STRTAB_STE_1_SHCFG_SHIFT 44
-#define STRTAB_STE_2_S2VMID_SHIFT 0
-#define STRTAB_STE_2_S2VMID_MASK 0xffffUL
-#define STRTAB_STE_2_VTCR_SHIFT 32
-#define STRTAB_STE_2_VTCR_MASK 0x7ffffUL
+#define STRTAB_STE_2_S2VMID GENMASK_ULL(15, 0)
+#define STRTAB_STE_2_VTCR GENMASK_ULL(50, 32)
#define STRTAB_STE_2_S2AA64 (1UL << 51)
#define STRTAB_STE_2_S2ENDI (1UL << 52)
#define STRTAB_STE_2_S2PTW (1UL << 54)
#define STRTAB_STE_2_S2R (1UL << 58)
-#define STRTAB_STE_3_S2TTB_SHIFT 4
-#define STRTAB_STE_3_S2TTB_MASK 0xfffffffffffUL
+#define STRTAB_STE_3_S2TTB_MASK GENMASK_ULL(51, 4)
/* Context descriptor (stage-1 only) */
#define CTXDESC_CD_DWORDS 8
-#define CTXDESC_CD_0_TCR_T0SZ_SHIFT 0
-#define ARM64_TCR_T0SZ_SHIFT 0
-#define ARM64_TCR_T0SZ_MASK 0x1fUL
-#define CTXDESC_CD_0_TCR_TG0_SHIFT 6
-#define ARM64_TCR_TG0_SHIFT 14
-#define ARM64_TCR_TG0_MASK 0x3UL
-#define CTXDESC_CD_0_TCR_IRGN0_SHIFT 8
-#define ARM64_TCR_IRGN0_SHIFT 8
-#define ARM64_TCR_IRGN0_MASK 0x3UL
-#define CTXDESC_CD_0_TCR_ORGN0_SHIFT 10
-#define ARM64_TCR_ORGN0_SHIFT 10
-#define ARM64_TCR_ORGN0_MASK 0x3UL
-#define CTXDESC_CD_0_TCR_SH0_SHIFT 12
-#define ARM64_TCR_SH0_SHIFT 12
-#define ARM64_TCR_SH0_MASK 0x3UL
-#define CTXDESC_CD_0_TCR_EPD0_SHIFT 14
-#define ARM64_TCR_EPD0_SHIFT 7
-#define ARM64_TCR_EPD0_MASK 0x1UL
-#define CTXDESC_CD_0_TCR_EPD1_SHIFT 30
-#define ARM64_TCR_EPD1_SHIFT 23
-#define ARM64_TCR_EPD1_MASK 0x1UL
+#define CTXDESC_CD_0_TCR_T0SZ GENMASK_ULL(5, 0)
+#define ARM64_TCR_T0SZ GENMASK_ULL(5, 0)
+#define CTXDESC_CD_0_TCR_TG0 GENMASK_ULL(7, 6)
+#define ARM64_TCR_TG0 GENMASK_ULL(15, 14)
+#define CTXDESC_CD_0_TCR_IRGN0 GENMASK_ULL(9, 8)
+#define ARM64_TCR_IRGN0 GENMASK_ULL(9, 8)
+#define CTXDESC_CD_0_TCR_ORGN0 GENMASK_ULL(11, 10)
+#define ARM64_TCR_ORGN0 GENMASK_ULL(11, 10)
+#define CTXDESC_CD_0_TCR_SH0 GENMASK_ULL(13, 12)
+#define ARM64_TCR_SH0 GENMASK_ULL(13, 12)
+#define CTXDESC_CD_0_TCR_EPD0 (1ULL << 14)
+#define ARM64_TCR_EPD0 (1ULL << 7)
+#define CTXDESC_CD_0_TCR_EPD1 (1ULL << 30)
+#define ARM64_TCR_EPD1 (1ULL << 23)
#define CTXDESC_CD_0_ENDI (1UL << 15)
#define CTXDESC_CD_0_V (1UL << 31)
-#define CTXDESC_CD_0_TCR_IPS_SHIFT 32
-#define ARM64_TCR_IPS_SHIFT 32
-#define ARM64_TCR_IPS_MASK 0x7UL
-#define CTXDESC_CD_0_TCR_TBI0_SHIFT 38
-#define ARM64_TCR_TBI0_SHIFT 37
-#define ARM64_TCR_TBI0_MASK 0x1UL
+#define CTXDESC_CD_0_TCR_IPS GENMASK_ULL(34, 32)
+#define ARM64_TCR_IPS GENMASK_ULL(34, 32)
+#define CTXDESC_CD_0_TCR_TBI0 (1ULL << 38)
+#define ARM64_TCR_TBI0 (1ULL << 37)
#define CTXDESC_CD_0_AA64 (1UL << 41)
#define CTXDESC_CD_0_S (1UL << 44)
#define CTXDESC_CD_0_R (1UL << 45)
#define CTXDESC_CD_0_A (1UL << 46)
-#define CTXDESC_CD_0_ASET_SHIFT 47
-#define CTXDESC_CD_0_ASET_SHARED (0UL << CTXDESC_CD_0_ASET_SHIFT)
-#define CTXDESC_CD_0_ASET_PRIVATE (1UL << CTXDESC_CD_0_ASET_SHIFT)
-#define CTXDESC_CD_0_ASID_SHIFT 48
-#define CTXDESC_CD_0_ASID_MASK 0xffffUL
-
-#define CTXDESC_CD_1_TTB0_SHIFT 4
-#define CTXDESC_CD_1_TTB0_MASK 0xfffffffffffUL
+#define CTXDESC_CD_0_ASET (1UL << 47)
+#define CTXDESC_CD_0_ASID GENMASK_ULL(63, 48)
-#define CTXDESC_CD_3_MAIR_SHIFT 0
+#define CTXDESC_CD_1_TTB0_MASK GENMASK_ULL(51, 4)
/* Convert between AArch64 (CPU) TCR format and SMMU CD format */
-#define ARM_SMMU_TCR2CD(tcr, fld) \
- (((tcr) >> ARM64_TCR_##fld##_SHIFT & ARM64_TCR_##fld##_MASK) \
- << CTXDESC_CD_0_TCR_##fld##_SHIFT)
+#define ARM_SMMU_TCR2CD(tcr, fld) FIELD_PREP(CTXDESC_CD_0_TCR_##fld, \
+ FIELD_GET(ARM64_TCR_##fld, tcr))
/* Command queue */
#define CMDQ_ENT_DWORDS 2
#define CMDQ_MAX_SZ_SHIFT 8
-#define CMDQ_ERR_SHIFT 24
-#define CMDQ_ERR_MASK 0x7f
+#define CMDQ_CONS_ERR GENMASK(30, 24)
#define CMDQ_ERR_CERROR_NONE_IDX 0
#define CMDQ_ERR_CERROR_ILL_IDX 1
#define CMDQ_ERR_CERROR_ABT_IDX 2
-#define CMDQ_0_OP_SHIFT 0
-#define CMDQ_0_OP_MASK 0xffUL
+#define CMDQ_0_OP GENMASK_ULL(7, 0)
#define CMDQ_0_SSV (1UL << 11)
-#define CMDQ_PREFETCH_0_SID_SHIFT 32
-#define CMDQ_PREFETCH_1_SIZE_SHIFT 0
-#define CMDQ_PREFETCH_1_ADDR_MASK ~0xfffUL
+#define CMDQ_PREFETCH_0_SID GENMASK_ULL(63, 32)
+#define CMDQ_PREFETCH_1_SIZE GENMASK_ULL(4, 0)
+#define CMDQ_PREFETCH_1_ADDR_MASK GENMASK_ULL(63, 12)
-#define CMDQ_CFGI_0_SID_SHIFT 32
-#define CMDQ_CFGI_0_SID_MASK 0xffffffffUL
+#define CMDQ_CFGI_0_SID GENMASK_ULL(63, 32)
#define CMDQ_CFGI_1_LEAF (1UL << 0)
-#define CMDQ_CFGI_1_RANGE_SHIFT 0
-#define CMDQ_CFGI_1_RANGE_MASK 0x1fUL
+#define CMDQ_CFGI_1_RANGE GENMASK_ULL(4, 0)
-#define CMDQ_TLBI_0_VMID_SHIFT 32
-#define CMDQ_TLBI_0_ASID_SHIFT 48
+#define CMDQ_TLBI_0_VMID GENMASK_ULL(47, 32)
+#define CMDQ_TLBI_0_ASID GENMASK_ULL(63, 48)
#define CMDQ_TLBI_1_LEAF (1UL << 0)
-#define CMDQ_TLBI_1_VA_MASK ~0xfffUL
-#define CMDQ_TLBI_1_IPA_MASK 0xfffffffff000UL
-
-#define CMDQ_PRI_0_SSID_SHIFT 12
-#define CMDQ_PRI_0_SSID_MASK 0xfffffUL
-#define CMDQ_PRI_0_SID_SHIFT 32
-#define CMDQ_PRI_0_SID_MASK 0xffffffffUL
-#define CMDQ_PRI_1_GRPID_SHIFT 0
-#define CMDQ_PRI_1_GRPID_MASK 0x1ffUL
-#define CMDQ_PRI_1_RESP_SHIFT 12
-#define CMDQ_PRI_1_RESP_DENY (0UL << CMDQ_PRI_1_RESP_SHIFT)
-#define CMDQ_PRI_1_RESP_FAIL (1UL << CMDQ_PRI_1_RESP_SHIFT)
-#define CMDQ_PRI_1_RESP_SUCC (2UL << CMDQ_PRI_1_RESP_SHIFT)
-
-#define CMDQ_SYNC_0_CS_SHIFT 12
-#define CMDQ_SYNC_0_CS_NONE (0UL << CMDQ_SYNC_0_CS_SHIFT)
-#define CMDQ_SYNC_0_CS_IRQ (1UL << CMDQ_SYNC_0_CS_SHIFT)
-#define CMDQ_SYNC_0_CS_SEV (2UL << CMDQ_SYNC_0_CS_SHIFT)
-#define CMDQ_SYNC_0_MSH_SHIFT 22
-#define CMDQ_SYNC_0_MSH_ISH (3UL << CMDQ_SYNC_0_MSH_SHIFT)
-#define CMDQ_SYNC_0_MSIATTR_SHIFT 24
-#define CMDQ_SYNC_0_MSIATTR_OIWB (0xfUL << CMDQ_SYNC_0_MSIATTR_SHIFT)
-#define CMDQ_SYNC_0_MSIDATA_SHIFT 32
-#define CMDQ_SYNC_0_MSIDATA_MASK 0xffffffffUL
-#define CMDQ_SYNC_1_MSIADDR_SHIFT 0
-#define CMDQ_SYNC_1_MSIADDR_MASK 0xffffffffffffcUL
+#define CMDQ_TLBI_1_VA_MASK GENMASK_ULL(63, 12)
+#define CMDQ_TLBI_1_IPA_MASK GENMASK_ULL(51, 12)
+
+#define CMDQ_PRI_0_SSID GENMASK_ULL(31, 12)
+#define CMDQ_PRI_0_SID GENMASK_ULL(63, 32)
+#define CMDQ_PRI_1_GRPID GENMASK_ULL(8, 0)
+#define CMDQ_PRI_1_RESP GENMASK_ULL(13, 12)
+
+#define CMDQ_SYNC_0_CS GENMASK_ULL(13, 12)
+#define CMDQ_SYNC_0_CS_NONE 0
+#define CMDQ_SYNC_0_CS_IRQ 1
+#define CMDQ_SYNC_0_CS_SEV 2
+#define CMDQ_SYNC_0_MSH GENMASK_ULL(23, 22)
+#define CMDQ_SYNC_0_MSIATTR GENMASK_ULL(27, 24)
+#define CMDQ_SYNC_0_MSIDATA GENMASK_ULL(63, 32)
+#define CMDQ_SYNC_1_MSIADDR_MASK GENMASK_ULL(51, 2)
/* Event queue */
#define EVTQ_ENT_DWORDS 4
#define EVTQ_MAX_SZ_SHIFT 7
-#define EVTQ_0_ID_SHIFT 0
-#define EVTQ_0_ID_MASK 0xffUL
+#define EVTQ_0_ID GENMASK_ULL(7, 0)
/* PRI queue */
#define PRIQ_ENT_DWORDS 2
#define PRIQ_MAX_SZ_SHIFT 8
-#define PRIQ_0_SID_SHIFT 0
-#define PRIQ_0_SID_MASK 0xffffffffUL
-#define PRIQ_0_SSID_SHIFT 32
-#define PRIQ_0_SSID_MASK 0xfffffUL
+#define PRIQ_0_SID GENMASK_ULL(31, 0)
+#define PRIQ_0_SSID GENMASK_ULL(51, 32)
#define PRIQ_0_PERM_PRIV (1UL << 58)
#define PRIQ_0_PERM_EXEC (1UL << 59)
#define PRIQ_0_PERM_READ (1UL << 60)
@@ -411,10 +355,8 @@
#define PRIQ_0_PRG_LAST (1UL << 62)
#define PRIQ_0_SSID_V (1UL << 63)
-#define PRIQ_1_PRG_IDX_SHIFT 0
-#define PRIQ_1_PRG_IDX_MASK 0x1ffUL
-#define PRIQ_1_ADDR_SHIFT 12
-#define PRIQ_1_ADDR_MASK 0xfffffffffffffUL
+#define PRIQ_1_PRG_IDX GENMASK_ULL(8, 0)
+#define PRIQ_1_ADDR_MASK GENMASK_ULL(63, 12)
/* High-level queue structures */
#define ARM_SMMU_POLL_TIMEOUT_US 100
@@ -430,9 +372,9 @@ MODULE_PARM_DESC(disable_bypass,
"Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU.");
enum pri_resp {
- PRI_RESP_DENY,
- PRI_RESP_FAIL,
- PRI_RESP_SUCC,
+ PRI_RESP_DENY = 0,
+ PRI_RESP_FAIL = 1,
+ PRI_RESP_SUCC = 2,
};
enum arm_smmu_msi_index {
@@ -611,6 +553,7 @@ struct arm_smmu_device {
#define ARM_SMMU_FEAT_STALLS (1 << 11)
#define ARM_SMMU_FEAT_HYP (1 << 12)
#define ARM_SMMU_FEAT_STALL_FORCE (1 << 13)
+#define ARM_SMMU_FEAT_VAX (1 << 14)
u32 features;
#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
@@ -836,67 +779,64 @@ static int queue_remove_raw(struct arm_smmu_queue *q, u64 *ent)
static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
{
memset(cmd, 0, CMDQ_ENT_DWORDS << 3);
- cmd[0] |= (ent->opcode & CMDQ_0_OP_MASK) << CMDQ_0_OP_SHIFT;
+ cmd[0] |= FIELD_PREP(CMDQ_0_OP, ent->opcode);
switch (ent->opcode) {
case CMDQ_OP_TLBI_EL2_ALL:
case CMDQ_OP_TLBI_NSNH_ALL:
break;
case CMDQ_OP_PREFETCH_CFG:
- cmd[0] |= (u64)ent->prefetch.sid << CMDQ_PREFETCH_0_SID_SHIFT;
- cmd[1] |= ent->prefetch.size << CMDQ_PREFETCH_1_SIZE_SHIFT;
+ cmd[0] |= FIELD_PREP(CMDQ_PREFETCH_0_SID, ent->prefetch.sid);
+ cmd[1] |= FIELD_PREP(CMDQ_PREFETCH_1_SIZE, ent->prefetch.size);
cmd[1] |= ent->prefetch.addr & CMDQ_PREFETCH_1_ADDR_MASK;
break;
case CMDQ_OP_CFGI_STE:
- cmd[0] |= (u64)ent->cfgi.sid << CMDQ_CFGI_0_SID_SHIFT;
- cmd[1] |= ent->cfgi.leaf ? CMDQ_CFGI_1_LEAF : 0;
+ cmd[0] |= FIELD_PREP(CMDQ_CFGI_0_SID, ent->cfgi.sid);
+ cmd[1] |= FIELD_PREP(CMDQ_CFGI_1_LEAF, ent->cfgi.leaf);
break;
case CMDQ_OP_CFGI_ALL:
/* Cover the entire SID range */
- cmd[1] |= CMDQ_CFGI_1_RANGE_MASK << CMDQ_CFGI_1_RANGE_SHIFT;
+ cmd[1] |= FIELD_PREP(CMDQ_CFGI_1_RANGE, 31);
break;
case CMDQ_OP_TLBI_NH_VA:
- cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT;
- cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0;
+ cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid);
+ cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_LEAF, ent->tlbi.leaf);
cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_VA_MASK;
break;
case CMDQ_OP_TLBI_S2_IPA:
- cmd[0] |= (u64)ent->tlbi.vmid << CMDQ_TLBI_0_VMID_SHIFT;
- cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0;
+ cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid);
+ cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_LEAF, ent->tlbi.leaf);
cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_IPA_MASK;
break;
case CMDQ_OP_TLBI_NH_ASID:
- cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT;
+ cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid);
/* Fallthrough */
case CMDQ_OP_TLBI_S12_VMALL:
- cmd[0] |= (u64)ent->tlbi.vmid << CMDQ_TLBI_0_VMID_SHIFT;
+ cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid);
break;
case CMDQ_OP_PRI_RESP:
- cmd[0] |= ent->substream_valid ? CMDQ_0_SSV : 0;
- cmd[0] |= ent->pri.ssid << CMDQ_PRI_0_SSID_SHIFT;
- cmd[0] |= (u64)ent->pri.sid << CMDQ_PRI_0_SID_SHIFT;
- cmd[1] |= ent->pri.grpid << CMDQ_PRI_1_GRPID_SHIFT;
+ cmd[0] |= FIELD_PREP(CMDQ_0_SSV, ent->substream_valid);
+ cmd[0] |= FIELD_PREP(CMDQ_PRI_0_SSID, ent->pri.ssid);
+ cmd[0] |= FIELD_PREP(CMDQ_PRI_0_SID, ent->pri.sid);
+ cmd[1] |= FIELD_PREP(CMDQ_PRI_1_GRPID, ent->pri.grpid);
switch (ent->pri.resp) {
case PRI_RESP_DENY:
- cmd[1] |= CMDQ_PRI_1_RESP_DENY;
- break;
case PRI_RESP_FAIL:
- cmd[1] |= CMDQ_PRI_1_RESP_FAIL;
- break;
case PRI_RESP_SUCC:
- cmd[1] |= CMDQ_PRI_1_RESP_SUCC;
break;
default:
return -EINVAL;
}
+ cmd[1] |= FIELD_PREP(CMDQ_PRI_1_RESP, ent->pri.resp);
break;
case CMDQ_OP_CMD_SYNC:
if (ent->sync.msiaddr)
- cmd[0] |= CMDQ_SYNC_0_CS_IRQ;
+ cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_IRQ);
else
- cmd[0] |= CMDQ_SYNC_0_CS_SEV;
- cmd[0] |= CMDQ_SYNC_0_MSH_ISH | CMDQ_SYNC_0_MSIATTR_OIWB;
- cmd[0] |= (u64)ent->sync.msidata << CMDQ_SYNC_0_MSIDATA_SHIFT;
+ cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_SEV);
+ cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSH, ARM_SMMU_SH_ISH);
+ cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIATTR, ARM_SMMU_MEMATTR_OIWB);
+ cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIDATA, ent->sync.msidata);
cmd[1] |= ent->sync.msiaddr & CMDQ_SYNC_1_MSIADDR_MASK;
break;
default:
@@ -918,7 +858,7 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
u64 cmd[CMDQ_ENT_DWORDS];
struct arm_smmu_queue *q = &smmu->cmdq.q;
u32 cons = readl_relaxed(q->cons_reg);
- u32 idx = cons >> CMDQ_ERR_SHIFT & CMDQ_ERR_MASK;
+ u32 idx = FIELD_GET(CMDQ_CONS_ERR, cons);
struct arm_smmu_cmdq_ent cmd_sync = {
.opcode = CMDQ_OP_CMD_SYNC,
};
@@ -1083,8 +1023,8 @@ static void arm_smmu_write_ctx_desc(struct arm_smmu_device *smmu,
#ifdef __BIG_ENDIAN
CTXDESC_CD_0_ENDI |
#endif
- CTXDESC_CD_0_R | CTXDESC_CD_0_A | CTXDESC_CD_0_ASET_PRIVATE |
- CTXDESC_CD_0_AA64 | (u64)cfg->cd.asid << CTXDESC_CD_0_ASID_SHIFT |
+ CTXDESC_CD_0_R | CTXDESC_CD_0_A | CTXDESC_CD_0_ASET |
+ CTXDESC_CD_0_AA64 | FIELD_PREP(CTXDESC_CD_0_ASID, cfg->cd.asid) |
CTXDESC_CD_0_V;
/* STALL_MODEL==0b10 && CD.S==0 is ILLEGAL */
@@ -1093,10 +1033,10 @@ static void arm_smmu_write_ctx_desc(struct arm_smmu_device *smmu,
cfg->cdptr[0] = cpu_to_le64(val);
- val = cfg->cd.ttbr & CTXDESC_CD_1_TTB0_MASK << CTXDESC_CD_1_TTB0_SHIFT;
+ val = cfg->cd.ttbr & CTXDESC_CD_1_TTB0_MASK;
cfg->cdptr[1] = cpu_to_le64(val);
- cfg->cdptr[3] = cpu_to_le64(cfg->cd.mair << CTXDESC_CD_3_MAIR_SHIFT);
+ cfg->cdptr[3] = cpu_to_le64(cfg->cd.mair);
}
/* Stream table manipulation functions */
@@ -1105,10 +1045,8 @@ arm_smmu_write_strtab_l1_desc(__le64 *dst, struct arm_smmu_strtab_l1_desc *desc)
{
u64 val = 0;
- val |= (desc->span & STRTAB_L1_DESC_SPAN_MASK)
- << STRTAB_L1_DESC_SPAN_SHIFT;
- val |= desc->l2ptr_dma &
- STRTAB_L1_DESC_L2PTR_MASK << STRTAB_L1_DESC_L2PTR_SHIFT;
+ val |= FIELD_PREP(STRTAB_L1_DESC_SPAN, desc->span);
+ val |= desc->l2ptr_dma & STRTAB_L1_DESC_L2PTR_MASK;
*dst = cpu_to_le64(val);
}
@@ -1156,10 +1094,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
};
if (val & STRTAB_STE_0_V) {
- u64 cfg;
-
- cfg = val & STRTAB_STE_0_CFG_MASK << STRTAB_STE_0_CFG_SHIFT;
- switch (cfg) {
+ switch (FIELD_GET(STRTAB_STE_0_CFG, val)) {
case STRTAB_STE_0_CFG_BYPASS:
break;
case STRTAB_STE_0_CFG_S1_TRANS:
@@ -1180,13 +1115,13 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
/* Bypass/fault */
if (!ste->assigned || !(ste->s1_cfg || ste->s2_cfg)) {
if (!ste->assigned && disable_bypass)
- val |= STRTAB_STE_0_CFG_ABORT;
+ val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT);
else
- val |= STRTAB_STE_0_CFG_BYPASS;
+ val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS);
dst[0] = cpu_to_le64(val);
- dst[1] = cpu_to_le64(STRTAB_STE_1_SHCFG_INCOMING
- << STRTAB_STE_1_SHCFG_SHIFT);
+ dst[1] = cpu_to_le64(FIELD_PREP(STRTAB_STE_1_SHCFG,
+ STRTAB_STE_1_SHCFG_INCOMING));
dst[2] = 0; /* Nuke the VMID */
/*
* The SMMU can perform negative caching, so we must sync
@@ -1200,41 +1135,36 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
if (ste->s1_cfg) {
BUG_ON(ste_live);
dst[1] = cpu_to_le64(
- STRTAB_STE_1_S1C_CACHE_WBRA
- << STRTAB_STE_1_S1CIR_SHIFT |
- STRTAB_STE_1_S1C_CACHE_WBRA
- << STRTAB_STE_1_S1COR_SHIFT |
- STRTAB_STE_1_S1C_SH_ISH << STRTAB_STE_1_S1CSH_SHIFT |
+ FIELD_PREP(STRTAB_STE_1_S1CIR, STRTAB_STE_1_S1C_CACHE_WBRA) |
+ FIELD_PREP(STRTAB_STE_1_S1COR, STRTAB_STE_1_S1C_CACHE_WBRA) |
+ FIELD_PREP(STRTAB_STE_1_S1CSH, ARM_SMMU_SH_ISH) |
#ifdef CONFIG_PCI_ATS
- STRTAB_STE_1_EATS_TRANS << STRTAB_STE_1_EATS_SHIFT |
+ FIELD_PREP(STRTAB_STE_1_EATS, STRTAB_STE_1_EATS_TRANS) |
#endif
- STRTAB_STE_1_STRW_NSEL1 << STRTAB_STE_1_STRW_SHIFT);
+ FIELD_PREP(STRTAB_STE_1_STRW, STRTAB_STE_1_STRW_NSEL1));
if (smmu->features & ARM_SMMU_FEAT_STALLS &&
!(smmu->features & ARM_SMMU_FEAT_STALL_FORCE))
dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
- val |= (ste->s1_cfg->cdptr_dma & STRTAB_STE_0_S1CTXPTR_MASK
- << STRTAB_STE_0_S1CTXPTR_SHIFT) |
- STRTAB_STE_0_CFG_S1_TRANS;
+ val |= (ste->s1_cfg->cdptr_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
+ FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS);
}
if (ste->s2_cfg) {
BUG_ON(ste_live);
dst[2] = cpu_to_le64(
- ste->s2_cfg->vmid << STRTAB_STE_2_S2VMID_SHIFT |
- (ste->s2_cfg->vtcr & STRTAB_STE_2_VTCR_MASK)
- << STRTAB_STE_2_VTCR_SHIFT |
+ FIELD_PREP(STRTAB_STE_2_S2VMID, ste->s2_cfg->vmid) |
+ FIELD_PREP(STRTAB_STE_2_VTCR, ste->s2_cfg->vtcr) |
#ifdef __BIG_ENDIAN
STRTAB_STE_2_S2ENDI |
#endif
STRTAB_STE_2_S2PTW | STRTAB_STE_2_S2AA64 |
STRTAB_STE_2_S2R);
- dst[3] = cpu_to_le64(ste->s2_cfg->vttbr &
- STRTAB_STE_3_S2TTB_MASK << STRTAB_STE_3_S2TTB_SHIFT);
+ dst[3] = cpu_to_le64(ste->s2_cfg->vttbr & STRTAB_STE_3_S2TTB_MASK);
- val |= STRTAB_STE_0_CFG_S2_TRANS;
+ val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S2_TRANS);
}
arm_smmu_sync_ste_for_sid(smmu, sid);
@@ -1295,7 +1225,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
do {
while (!queue_remove_raw(q, evt)) {
- u8 id = evt[0] >> EVTQ_0_ID_SHIFT & EVTQ_0_ID_MASK;
+ u8 id = FIELD_GET(EVTQ_0_ID, evt[0]);
dev_info(smmu->dev, "event 0x%02x received:\n", id);
for (i = 0; i < ARRAY_SIZE(evt); ++i)
@@ -1323,11 +1253,11 @@ static void arm_smmu_handle_ppr(struct arm_smmu_device *smmu, u64 *evt)
u16 grpid;
bool ssv, last;
- sid = evt[0] >> PRIQ_0_SID_SHIFT & PRIQ_0_SID_MASK;
- ssv = evt[0] & PRIQ_0_SSID_V;
- ssid = ssv ? evt[0] >> PRIQ_0_SSID_SHIFT & PRIQ_0_SSID_MASK : 0;
- last = evt[0] & PRIQ_0_PRG_LAST;
- grpid = evt[1] >> PRIQ_1_PRG_IDX_SHIFT & PRIQ_1_PRG_IDX_MASK;
+ sid = FIELD_GET(PRIQ_0_SID, evt[0]);
+ ssv = FIELD_GET(PRIQ_0_SSID_V, evt[0]);
+ ssid = ssv ? FIELD_GET(PRIQ_0_SSID, evt[0]) : 0;
+ last = FIELD_GET(PRIQ_0_PRG_LAST, evt[0]);
+ grpid = FIELD_GET(PRIQ_1_PRG_IDX, evt[1]);
dev_info(smmu->dev, "unexpected PRI request received:\n");
dev_info(smmu->dev,
@@ -1337,7 +1267,7 @@ static void arm_smmu_handle_ppr(struct arm_smmu_device *smmu, u64 *evt)
evt[0] & PRIQ_0_PERM_READ ? "R" : "",
evt[0] & PRIQ_0_PERM_WRITE ? "W" : "",
evt[0] & PRIQ_0_PERM_EXEC ? "X" : "",
- evt[1] & PRIQ_1_ADDR_MASK << PRIQ_1_ADDR_SHIFT);
+ evt[1] & PRIQ_1_ADDR_MASK);
if (last) {
struct arm_smmu_cmdq_ent cmd = {
@@ -1664,7 +1594,8 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
switch (smmu_domain->stage) {
case ARM_SMMU_DOMAIN_S1:
- ias = VA_BITS;
+ ias = (smmu->features & ARM_SMMU_FEAT_VAX) ? 52 : 48;
+ ias = min_t(unsigned long, ias, VA_BITS);
oas = smmu->ias;
fmt = ARM_64_LPAE_S1;
finalise_stage_fn = arm_smmu_domain_finalise_s1;
@@ -1696,7 +1627,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
return -ENOMEM;
domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
- domain->geometry.aperture_end = (1UL << ias) - 1;
+ domain->geometry.aperture_end = (1UL << pgtbl_cfg.ias) - 1;
domain->geometry.force_aperture = true;
ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg);
@@ -2102,9 +2033,8 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
q->ent_dwords = dwords;
q->q_base = Q_BASE_RWA;
- q->q_base |= q->base_dma & Q_BASE_ADDR_MASK << Q_BASE_ADDR_SHIFT;
- q->q_base |= (q->max_n_shift & Q_BASE_LOG2SIZE_MASK)
- << Q_BASE_LOG2SIZE_SHIFT;
+ q->q_base |= q->base_dma & Q_BASE_ADDR_MASK;
+ q->q_base |= FIELD_PREP(Q_BASE_LOG2SIZE, q->max_n_shift);
q->prod = q->cons = 0;
return 0;
@@ -2186,11 +2116,9 @@ static int arm_smmu_init_strtab_2lvl(struct arm_smmu_device *smmu)
cfg->strtab = strtab;
/* Configure strtab_base_cfg for 2 levels */
- reg = STRTAB_BASE_CFG_FMT_2LVL;
- reg |= (size & STRTAB_BASE_CFG_LOG2SIZE_MASK)
- << STRTAB_BASE_CFG_LOG2SIZE_SHIFT;
- reg |= (STRTAB_SPLIT & STRTAB_BASE_CFG_SPLIT_MASK)
- << STRTAB_BASE_CFG_SPLIT_SHIFT;
+ reg = FIELD_PREP(STRTAB_BASE_CFG_FMT, STRTAB_BASE_CFG_FMT_2LVL);
+ reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, size);
+ reg |= FIELD_PREP(STRTAB_BASE_CFG_SPLIT, STRTAB_SPLIT);
cfg->strtab_base_cfg = reg;
return arm_smmu_init_l1_strtab(smmu);
@@ -2216,9 +2144,8 @@ static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu)
cfg->num_l1_ents = 1 << smmu->sid_bits;
/* Configure strtab_base_cfg for a linear table covering all SIDs */
- reg = STRTAB_BASE_CFG_FMT_LINEAR;
- reg |= (smmu->sid_bits & STRTAB_BASE_CFG_LOG2SIZE_MASK)
- << STRTAB_BASE_CFG_LOG2SIZE_SHIFT;
+ reg = FIELD_PREP(STRTAB_BASE_CFG_FMT, STRTAB_BASE_CFG_FMT_LINEAR);
+ reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, smmu->sid_bits);
cfg->strtab_base_cfg = reg;
arm_smmu_init_bypass_stes(strtab, cfg->num_l1_ents);
@@ -2239,8 +2166,7 @@ static int arm_smmu_init_strtab(struct arm_smmu_device *smmu)
return ret;
/* Set the strtab base address */
- reg = smmu->strtab_cfg.strtab_dma &
- STRTAB_BASE_ADDR_MASK << STRTAB_BASE_ADDR_SHIFT;
+ reg = smmu->strtab_cfg.strtab_dma & STRTAB_BASE_ADDR_MASK;
reg |= STRTAB_BASE_RA;
smmu->strtab_cfg.strtab_base = reg;
@@ -2303,11 +2229,11 @@ static void arm_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
phys_addr_t *cfg = arm_smmu_msi_cfg[desc->platform.msi_index];
doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo;
- doorbell &= MSI_CFG0_ADDR_MASK << MSI_CFG0_ADDR_SHIFT;
+ doorbell &= MSI_CFG0_ADDR_MASK;
writeq_relaxed(doorbell, smmu->base + cfg[0]);
writel_relaxed(msg->data, smmu->base + cfg[1]);
- writel_relaxed(MSI_CFG2_MEMATTR_DEVICE_nGnRE, smmu->base + cfg[2]);
+ writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE, smmu->base + cfg[2]);
}
static void arm_smmu_setup_msis(struct arm_smmu_device *smmu)
@@ -2328,10 +2254,15 @@ static void arm_smmu_setup_msis(struct arm_smmu_device *smmu)
if (!(smmu->features & ARM_SMMU_FEAT_MSI))
return;
+ if (!dev->msi_domain) {
+ dev_info(smmu->dev, "msi_domain absent - falling back to wired irqs\n");
+ return;
+ }
+
/* Allocate MSIs for evtq, gerror and priq. Ignore cmdq */
ret = platform_msi_domain_alloc_irqs(dev, nvec, arm_smmu_write_msi_msg);
if (ret) {
- dev_warn(dev, "failed to allocate MSIs\n");
+ dev_warn(dev, "failed to allocate MSIs - falling back to wired irqs\n");
return;
}
@@ -2370,6 +2301,8 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)
"arm-smmu-v3-evtq", smmu);
if (ret < 0)
dev_warn(smmu->dev, "failed to enable evtq irq\n");
+ } else {
+ dev_warn(smmu->dev, "no evtq irq - events will not be reported!\n");
}
irq = smmu->gerr_irq;
@@ -2378,6 +2311,8 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)
0, "arm-smmu-v3-gerror", smmu);
if (ret < 0)
dev_warn(smmu->dev, "failed to enable gerror irq\n");
+ } else {
+ dev_warn(smmu->dev, "no gerr irq - errors will not be reported!\n");
}
if (smmu->features & ARM_SMMU_FEAT_PRI) {
@@ -2391,6 +2326,8 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)
if (ret < 0)
dev_warn(smmu->dev,
"failed to enable priq irq\n");
+ } else {
+ dev_warn(smmu->dev, "no priq irq - PRI will be broken\n");
}
}
}
@@ -2463,12 +2400,12 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
return ret;
/* CR1 (table and queue memory attributes) */
- reg = (CR1_SH_ISH << CR1_TABLE_SH_SHIFT) |
- (CR1_CACHE_WB << CR1_TABLE_OC_SHIFT) |
- (CR1_CACHE_WB << CR1_TABLE_IC_SHIFT) |
- (CR1_SH_ISH << CR1_QUEUE_SH_SHIFT) |
- (CR1_CACHE_WB << CR1_QUEUE_OC_SHIFT) |
- (CR1_CACHE_WB << CR1_QUEUE_IC_SHIFT);
+ reg = FIELD_PREP(CR1_TABLE_SH, ARM_SMMU_SH_ISH) |
+ FIELD_PREP(CR1_TABLE_OC, CR1_CACHE_WB) |
+ FIELD_PREP(CR1_TABLE_IC, CR1_CACHE_WB) |
+ FIELD_PREP(CR1_QUEUE_SH, ARM_SMMU_SH_ISH) |
+ FIELD_PREP(CR1_QUEUE_OC, CR1_CACHE_WB) |
+ FIELD_PREP(CR1_QUEUE_IC, CR1_CACHE_WB);
writel_relaxed(reg, smmu->base + ARM_SMMU_CR1);
/* CR2 (random crap) */
@@ -2578,7 +2515,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
/* 2-level structures */
- if ((reg & IDR0_ST_LVL_MASK << IDR0_ST_LVL_SHIFT) == IDR0_ST_LVL_2LVL)
+ if (FIELD_GET(IDR0_ST_LVL, reg) == IDR0_ST_LVL_2LVL)
smmu->features |= ARM_SMMU_FEAT_2_LVL_STRTAB;
if (reg & IDR0_CD2L)
@@ -2589,7 +2526,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
* We currently require the same endianness as the CPU, but this
* could be changed later by adding a new IO_PGTABLE_QUIRK.
*/
- switch (reg & IDR0_TTENDIAN_MASK << IDR0_TTENDIAN_SHIFT) {
+ switch (FIELD_GET(IDR0_TTENDIAN, reg)) {
case IDR0_TTENDIAN_MIXED:
smmu->features |= ARM_SMMU_FEAT_TT_LE | ARM_SMMU_FEAT_TT_BE;
break;
@@ -2631,7 +2568,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
dev_warn(smmu->dev, "IDR0.COHACC overridden by FW configuration (%s)\n",
coherent ? "true" : "false");
- switch (reg & IDR0_STALL_MODEL_MASK << IDR0_STALL_MODEL_SHIFT) {
+ switch (FIELD_GET(IDR0_STALL_MODEL, reg)) {
case IDR0_STALL_MODEL_FORCE:
smmu->features |= ARM_SMMU_FEAT_STALL_FORCE;
/* Fallthrough */
@@ -2651,7 +2588,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
}
/* We only support the AArch64 table format at present */
- switch (reg & IDR0_TTF_MASK << IDR0_TTF_SHIFT) {
+ switch (FIELD_GET(IDR0_TTF, reg)) {
case IDR0_TTF_AARCH32_64:
smmu->ias = 40;
/* Fallthrough */
@@ -2674,22 +2611,22 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
}
/* Queue sizes, capped at 4k */
- smmu->cmdq.q.max_n_shift = min((u32)CMDQ_MAX_SZ_SHIFT,
- reg >> IDR1_CMDQ_SHIFT & IDR1_CMDQ_MASK);
+ smmu->cmdq.q.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT,
+ FIELD_GET(IDR1_CMDQS, reg));
if (!smmu->cmdq.q.max_n_shift) {
/* Odd alignment restrictions on the base, so ignore for now */
dev_err(smmu->dev, "unit-length command queue not supported\n");
return -ENXIO;
}
- smmu->evtq.q.max_n_shift = min((u32)EVTQ_MAX_SZ_SHIFT,
- reg >> IDR1_EVTQ_SHIFT & IDR1_EVTQ_MASK);
- smmu->priq.q.max_n_shift = min((u32)PRIQ_MAX_SZ_SHIFT,
- reg >> IDR1_PRIQ_SHIFT & IDR1_PRIQ_MASK);
+ smmu->evtq.q.max_n_shift = min_t(u32, EVTQ_MAX_SZ_SHIFT,
+ FIELD_GET(IDR1_EVTQS, reg));
+ smmu->priq.q.max_n_shift = min_t(u32, PRIQ_MAX_SZ_SHIFT,
+ FIELD_GET(IDR1_PRIQS, reg));
/* SID/SSID sizes */
- smmu->ssid_bits = reg >> IDR1_SSID_SHIFT & IDR1_SSID_MASK;
- smmu->sid_bits = reg >> IDR1_SID_SHIFT & IDR1_SID_MASK;
+ smmu->ssid_bits = FIELD_GET(IDR1_SSIDSIZE, reg);
+ smmu->sid_bits = FIELD_GET(IDR1_SIDSIZE, reg);
/*
* If the SMMU supports fewer bits than would fill a single L2 stream
@@ -2702,8 +2639,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
/* Maximum number of outstanding stalls */
- smmu->evtq.max_stalls = reg >> IDR5_STALL_MAX_SHIFT
- & IDR5_STALL_MAX_MASK;
+ smmu->evtq.max_stalls = FIELD_GET(IDR5_STALL_MAX, reg);
/* Page sizes */
if (reg & IDR5_GRAN64K)
@@ -2713,13 +2649,12 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
if (reg & IDR5_GRAN4K)
smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
- if (arm_smmu_ops.pgsize_bitmap == -1UL)
- arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap;
- else
- arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap;
+ /* Input address size */
+ if (FIELD_GET(IDR5_VAX, reg) == IDR5_VAX_52_BIT)
+ smmu->features |= ARM_SMMU_FEAT_VAX;
/* Output address size */
- switch (reg & IDR5_OAS_MASK << IDR5_OAS_SHIFT) {
+ switch (FIELD_GET(IDR5_OAS, reg)) {
case IDR5_OAS_32_BIT:
smmu->oas = 32;
break;
@@ -2735,6 +2670,10 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
case IDR5_OAS_44_BIT:
smmu->oas = 44;
break;
+ case IDR5_OAS_52_BIT:
+ smmu->oas = 52;
+ smmu->pgsize_bitmap |= 1ULL << 42; /* 4TB */
+ break;
default:
dev_info(smmu->dev,
"unknown output address size. Truncating to 48-bit\n");
@@ -2743,6 +2682,11 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
smmu->oas = 48;
}
+ if (arm_smmu_ops.pgsize_bitmap == -1UL)
+ arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap;
+ else
+ arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap;
+
/* Set the DMA mask for our table walker */
if (dma_set_mask_and_coherent(smmu->dev, DMA_BIT_MASK(smmu->oas)))
dev_warn(smmu->dev,
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 25914d36c5ac..f05f3cf90756 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/acpi_iort.h>
#include <linux/device.h>
#include <linux/dma-iommu.h>
#include <linux/gfp.h>
@@ -167,13 +168,18 @@ EXPORT_SYMBOL(iommu_put_dma_cookie);
*
* IOMMU drivers can use this to implement their .get_resv_regions callback
* for general non-IOMMU-specific reservations. Currently, this covers host
- * bridge windows for PCI devices.
+ * bridge windows for PCI devices and GICv3 ITS region reservation on ACPI
+ * based ARM platforms that may require HW MSI reservation.
*/
void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
{
struct pci_host_bridge *bridge;
struct resource_entry *window;
+ if (!is_of_node(dev->iommu_fwspec->iommu_fwnode) &&
+ iort_iommu_msi_get_resv_regions(dev, list) < 0)
+ return;
+
if (!dev_is_pci(dev))
return;
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 9a7ffd13c7f0..accf58388bdb 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -806,7 +806,7 @@ int __init dmar_dev_scope_init(void)
return dmar_dev_scope_status;
}
-void dmar_register_bus_notifier(void)
+void __init dmar_register_bus_notifier(void)
{
bus_register_notifier(&pci_bus_type, &dmar_pci_bus_nb);
}
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index c5f4f7691b57..85879cfec52f 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1239,17 +1239,6 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain,
return phys;
}
-static struct iommu_group *get_device_iommu_group(struct device *dev)
-{
- struct iommu_group *group;
-
- group = iommu_group_get(dev);
- if (!group)
- group = iommu_group_alloc();
-
- return group;
-}
-
static int exynos_iommu_add_device(struct device *dev)
{
struct exynos_iommu_owner *owner = dev->archdata.iommu;
@@ -1345,7 +1334,7 @@ static const struct iommu_ops exynos_iommu_ops = {
.unmap = exynos_iommu_unmap,
.map_sg = default_iommu_map_sg,
.iova_to_phys = exynos_iommu_iova_to_phys,
- .device_group = get_device_iommu_group,
+ .device_group = generic_device_group,
.add_device = exynos_iommu_add_device,
.remove_device = exynos_iommu_remove_device,
.pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 24d1b1b42013..749d8f235346 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -5043,7 +5043,6 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain,
{
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
struct page *freelist = NULL;
- struct intel_iommu *iommu;
unsigned long start_pfn, last_pfn;
unsigned int npages;
int iommu_id, level = 0;
@@ -5062,12 +5061,9 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain,
npages = last_pfn - start_pfn + 1;
- for_each_domain_iommu(iommu_id, dmar_domain) {
- iommu = g_iommus[iommu_id];
-
+ for_each_domain_iommu(iommu_id, dmar_domain)
iommu_flush_iotlb_psi(g_iommus[iommu_id], dmar_domain,
start_pfn, npages, !freelist, 0);
- }
dma_free_pagelist(freelist);
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index 99bc9bd64b9e..e8cd984cf9c8 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -396,6 +396,7 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
pasid_max - 1, GFP_KERNEL);
if (ret < 0) {
kfree(svm);
+ kfree(sdev);
goto out;
}
svm->pasid = ret;
@@ -422,17 +423,13 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
iommu->pasid_table[svm->pasid].val = pasid_entry_val;
wmb();
- /* In caching mode, we still have to flush with PASID 0 when
- * a PASID table entry becomes present. Not entirely clear
- * *why* that would be the case — surely we could just issue
- * a flush with the PASID value that we've changed? The PASID
- * is the index into the table, after all. It's not like domain
- * IDs in the case of the equivalent context-entry change in
- * caching mode. And for that matter it's not entirely clear why
- * a VMM would be in the business of caching the PASID table
- * anyway. Surely that can be left entirely to the guest? */
+
+ /*
+ * Flush PASID cache when a PASID table entry becomes
+ * present.
+ */
if (cap_caching_mode(iommu->cap))
- intel_flush_pasid_dev(svm, sdev, 0);
+ intel_flush_pasid_dev(svm, sdev, svm->pasid);
}
list_add_rcu(&sdev->list, &svm->devs);
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index 2ca08dc9331c..10e4a3d11c02 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -357,8 +357,8 @@ static bool arm_v7s_pte_is_cont(arm_v7s_iopte pte, int lvl)
return false;
}
-static int __arm_v7s_unmap(struct arm_v7s_io_pgtable *, unsigned long,
- size_t, int, arm_v7s_iopte *);
+static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *, unsigned long,
+ size_t, int, arm_v7s_iopte *);
static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data,
unsigned long iova, phys_addr_t paddr, int prot,
@@ -541,9 +541,10 @@ static arm_v7s_iopte arm_v7s_split_cont(struct arm_v7s_io_pgtable *data,
return pte;
}
-static int arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data,
- unsigned long iova, size_t size,
- arm_v7s_iopte blk_pte, arm_v7s_iopte *ptep)
+static size_t arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data,
+ unsigned long iova, size_t size,
+ arm_v7s_iopte blk_pte,
+ arm_v7s_iopte *ptep)
{
struct io_pgtable_cfg *cfg = &data->iop.cfg;
arm_v7s_iopte pte, *tablep;
@@ -584,9 +585,9 @@ static int arm_v7s_split_blk_unmap(struct arm_v7s_io_pgtable *data,
return size;
}
-static int __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
- unsigned long iova, size_t size, int lvl,
- arm_v7s_iopte *ptep)
+static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
+ unsigned long iova, size_t size, int lvl,
+ arm_v7s_iopte *ptep)
{
arm_v7s_iopte pte[ARM_V7S_CONT_PAGES];
struct io_pgtable *iop = &data->iop;
@@ -656,8 +657,8 @@ static int __arm_v7s_unmap(struct arm_v7s_io_pgtable *data,
return __arm_v7s_unmap(data, iova, size, lvl + 1, ptep);
}
-static int arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova,
- size_t size)
+static size_t arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova,
+ size_t size)
{
struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops);
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 51e5c43caed1..39c2a056da21 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -21,6 +21,7 @@
#define pr_fmt(fmt) "arm-lpae io-pgtable: " fmt
#include <linux/atomic.h>
+#include <linux/bitops.h>
#include <linux/iommu.h>
#include <linux/kernel.h>
#include <linux/sizes.h>
@@ -32,7 +33,7 @@
#include "io-pgtable.h"
-#define ARM_LPAE_MAX_ADDR_BITS 48
+#define ARM_LPAE_MAX_ADDR_BITS 52
#define ARM_LPAE_S2_MAX_CONCAT_PAGES 16
#define ARM_LPAE_MAX_LEVELS 4
@@ -86,6 +87,8 @@
#define ARM_LPAE_PTE_TYPE_TABLE 3
#define ARM_LPAE_PTE_TYPE_PAGE 3
+#define ARM_LPAE_PTE_ADDR_MASK GENMASK_ULL(47,12)
+
#define ARM_LPAE_PTE_NSTABLE (((arm_lpae_iopte)1) << 63)
#define ARM_LPAE_PTE_XN (((arm_lpae_iopte)3) << 53)
#define ARM_LPAE_PTE_AF (((arm_lpae_iopte)1) << 10)
@@ -159,6 +162,7 @@
#define ARM_LPAE_TCR_PS_42_BIT 0x3ULL
#define ARM_LPAE_TCR_PS_44_BIT 0x4ULL
#define ARM_LPAE_TCR_PS_48_BIT 0x5ULL
+#define ARM_LPAE_TCR_PS_52_BIT 0x6ULL
#define ARM_LPAE_MAIR_ATTR_SHIFT(n) ((n) << 3)
#define ARM_LPAE_MAIR_ATTR_MASK 0xff
@@ -170,9 +174,7 @@
#define ARM_LPAE_MAIR_ATTR_IDX_DEV 2
/* IOPTE accessors */
-#define iopte_deref(pte,d) \
- (__va((pte) & ((1ULL << ARM_LPAE_MAX_ADDR_BITS) - 1) \
- & ~(ARM_LPAE_GRANULE(d) - 1ULL)))
+#define iopte_deref(pte,d) __va(iopte_to_paddr(pte, d))
#define iopte_type(pte,l) \
(((pte) >> ARM_LPAE_PTE_TYPE_SHIFT) & ARM_LPAE_PTE_TYPE_MASK)
@@ -184,12 +186,6 @@
(iopte_type(pte,l) == ARM_LPAE_PTE_TYPE_PAGE) : \
(iopte_type(pte,l) == ARM_LPAE_PTE_TYPE_BLOCK))
-#define iopte_to_pfn(pte,d) \
- (((pte) & ((1ULL << ARM_LPAE_MAX_ADDR_BITS) - 1)) >> (d)->pg_shift)
-
-#define pfn_to_iopte(pfn,d) \
- (((pfn) << (d)->pg_shift) & ((1ULL << ARM_LPAE_MAX_ADDR_BITS) - 1))
-
struct arm_lpae_io_pgtable {
struct io_pgtable iop;
@@ -203,6 +199,27 @@ struct arm_lpae_io_pgtable {
typedef u64 arm_lpae_iopte;
+static arm_lpae_iopte paddr_to_iopte(phys_addr_t paddr,
+ struct arm_lpae_io_pgtable *data)
+{
+ arm_lpae_iopte pte = paddr;
+
+ /* Of the bits which overlap, either 51:48 or 15:12 are always RES0 */
+ return (pte | (pte >> (48 - 12))) & ARM_LPAE_PTE_ADDR_MASK;
+}
+
+static phys_addr_t iopte_to_paddr(arm_lpae_iopte pte,
+ struct arm_lpae_io_pgtable *data)
+{
+ u64 paddr = pte & ARM_LPAE_PTE_ADDR_MASK;
+
+ if (data->pg_shift < 16)
+ return paddr;
+
+ /* Rotate the packed high-order bits back to the top */
+ return (paddr | (paddr << (48 - 12))) & (ARM_LPAE_PTE_ADDR_MASK << 4);
+}
+
static bool selftest_running = false;
static dma_addr_t __arm_lpae_dma_addr(void *pages)
@@ -268,9 +285,9 @@ static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte,
__arm_lpae_sync_pte(ptep, cfg);
}
-static int __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
- unsigned long iova, size_t size, int lvl,
- arm_lpae_iopte *ptep);
+static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
+ unsigned long iova, size_t size, 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,
@@ -287,7 +304,7 @@ static void __arm_lpae_init_pte(struct arm_lpae_io_pgtable *data,
pte |= ARM_LPAE_PTE_TYPE_BLOCK;
pte |= ARM_LPAE_PTE_AF | ARM_LPAE_PTE_SH_IS;
- pte |= pfn_to_iopte(paddr >> data->pg_shift, data);
+ pte |= paddr_to_iopte(paddr, data);
__arm_lpae_set_pte(ptep, pte, &data->iop.cfg);
}
@@ -506,10 +523,10 @@ static void arm_lpae_free_pgtable(struct io_pgtable *iop)
kfree(data);
}
-static int arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
- unsigned long iova, size_t size,
- arm_lpae_iopte blk_pte, int lvl,
- arm_lpae_iopte *ptep)
+static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
+ unsigned long iova, size_t size,
+ arm_lpae_iopte blk_pte, int lvl,
+ arm_lpae_iopte *ptep)
{
struct io_pgtable_cfg *cfg = &data->iop.cfg;
arm_lpae_iopte pte, *tablep;
@@ -528,7 +545,7 @@ static int arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
if (size == split_sz)
unmap_idx = ARM_LPAE_LVL_IDX(iova, lvl, data);
- blk_paddr = iopte_to_pfn(blk_pte, data) << data->pg_shift;
+ 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) {
@@ -560,9 +577,9 @@ static int arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
return size;
}
-static int __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
- unsigned long iova, size_t size, int lvl,
- arm_lpae_iopte *ptep)
+static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
+ unsigned long iova, size_t size, int lvl,
+ arm_lpae_iopte *ptep)
{
arm_lpae_iopte pte;
struct io_pgtable *iop = &data->iop;
@@ -606,8 +623,8 @@ static int __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
return __arm_lpae_unmap(data, iova, size, lvl + 1, ptep);
}
-static int arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
- size_t size)
+static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
+ size_t size)
{
struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
arm_lpae_iopte *ptep = data->pgd;
@@ -652,12 +669,13 @@ static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
found_translation:
iova &= (ARM_LPAE_BLOCK_SIZE(lvl, data) - 1);
- return ((phys_addr_t)iopte_to_pfn(pte,data) << data->pg_shift) | iova;
+ return iopte_to_paddr(pte, data) | iova;
}
static void arm_lpae_restrict_pgsizes(struct io_pgtable_cfg *cfg)
{
- unsigned long granule;
+ unsigned long granule, page_sizes;
+ unsigned int max_addr_bits = 48;
/*
* We need to restrict the supported page sizes to match the
@@ -677,17 +695,24 @@ static void arm_lpae_restrict_pgsizes(struct io_pgtable_cfg *cfg)
switch (granule) {
case SZ_4K:
- cfg->pgsize_bitmap &= (SZ_4K | SZ_2M | SZ_1G);
+ page_sizes = (SZ_4K | SZ_2M | SZ_1G);
break;
case SZ_16K:
- cfg->pgsize_bitmap &= (SZ_16K | SZ_32M);
+ page_sizes = (SZ_16K | SZ_32M);
break;
case SZ_64K:
- cfg->pgsize_bitmap &= (SZ_64K | SZ_512M);
+ max_addr_bits = 52;
+ page_sizes = (SZ_64K | SZ_512M);
+ if (cfg->oas > 48)
+ page_sizes |= 1ULL << 42; /* 4TB */
break;
default:
- cfg->pgsize_bitmap = 0;
+ page_sizes = 0;
}
+
+ cfg->pgsize_bitmap &= page_sizes;
+ cfg->ias = min(cfg->ias, max_addr_bits);
+ cfg->oas = min(cfg->oas, max_addr_bits);
}
static struct arm_lpae_io_pgtable *
@@ -784,6 +809,9 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
case 48:
reg |= (ARM_LPAE_TCR_PS_48_BIT << ARM_LPAE_TCR_IPS_SHIFT);
break;
+ case 52:
+ reg |= (ARM_LPAE_TCR_PS_52_BIT << ARM_LPAE_TCR_IPS_SHIFT);
+ break;
default:
goto out_free_data;
}
@@ -891,6 +919,9 @@ arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie)
case 48:
reg |= (ARM_LPAE_TCR_PS_48_BIT << ARM_LPAE_TCR_PS_SHIFT);
break;
+ case 52:
+ reg |= (ARM_LPAE_TCR_PS_52_BIT << ARM_LPAE_TCR_PS_SHIFT);
+ break;
default:
goto out_free_data;
}
diff --git a/drivers/iommu/io-pgtable.h b/drivers/iommu/io-pgtable.h
index cd2e1eafffe6..2df79093cad9 100644
--- a/drivers/iommu/io-pgtable.h
+++ b/drivers/iommu/io-pgtable.h
@@ -119,8 +119,8 @@ 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);
- int (*unmap)(struct io_pgtable_ops *ops, unsigned long iova,
- size_t size);
+ size_t (*unmap)(struct io_pgtable_ops *ops, unsigned long iova,
+ size_t size);
phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops,
unsigned long iova);
};
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 69fef991c651..d2aa23202bb9 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1573,10 +1573,10 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
if (unlikely(ops->unmap == NULL ||
domain->pgsize_bitmap == 0UL))
- return -ENODEV;
+ return 0;
if (unlikely(!(domain->type & __IOMMU_DOMAIN_PAGING)))
- return -EINVAL;
+ return 0;
/* find out the minimum page size supported */
min_pagesz = 1 << __ffs(domain->pgsize_bitmap);
@@ -1589,7 +1589,7 @@ static size_t __iommu_unmap(struct iommu_domain *domain,
if (!IS_ALIGNED(iova | size, min_pagesz)) {
pr_err("unaligned: iova 0x%lx size 0x%zx min_pagesz 0x%x\n",
iova, size, min_pagesz);
- return -EINVAL;
+ return 0;
}
pr_debug("unmap this: iova 0x%lx size 0x%zx\n", iova, size);
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index f227d73e7bf6..f2832a10fcea 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -60,7 +60,7 @@
(((prot) & 0x3) << F_MMU_TF_PROTECT_SEL_SHIFT(data))
#define REG_MMU_IVRP_PADDR 0x114
-#define F_MMU_IVRP_PA_SET(pa, ext) (((pa) >> 1) | ((!!(ext)) << 31))
+
#define REG_MMU_VLD_PA_RNG 0x118
#define F_MMU_VLD_PA_RNG(EA, SA) (((EA) << 8) | (SA))
@@ -539,8 +539,13 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
- writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base, data->enable_4GB),
- data->base + REG_MMU_IVRP_PADDR);
+ if (data->m4u_plat == M4U_MT8173)
+ regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
+ else
+ regval = lower_32_bits(data->protect_base) |
+ upper_32_bits(data->protect_base);
+ writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
+
if (data->enable_4GB && data->m4u_plat != M4U_MT8173) {
/*
* If 4GB mode is enabled, the validate PA range is from
@@ -695,6 +700,7 @@ static int __maybe_unused mtk_iommu_suspend(struct device *dev)
reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG);
reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0);
reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL);
+ reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR);
clk_disable_unprepare(data->bclk);
return 0;
}
@@ -717,8 +723,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG);
writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
- writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base, data->enable_4GB),
- base + REG_MMU_IVRP_PADDR);
+ writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
if (data->m4u_dom)
writel(data->m4u_dom->cfg.arm_v7s_cfg.ttbr[0],
base + REG_MMU_PT_BASE_ADDR);
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index b4451a1c7c2f..778498b8633f 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -32,6 +32,7 @@ struct mtk_iommu_suspend_reg {
u32 ctrl_reg;
u32 int_control0;
u32 int_main_control;
+ u32 ivrp_paddr;
};
enum mtk_iommu_plat {
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 5a96fd14ac22..a7c2a973784f 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -417,20 +417,12 @@ static int mtk_iommu_create_mapping(struct device *dev,
m4udev->archdata.iommu = mtk_mapping;
}
- ret = arm_iommu_attach_device(dev, mtk_mapping);
- if (ret)
- goto err_release_mapping;
-
return 0;
-
-err_release_mapping:
- arm_iommu_release_mapping(mtk_mapping);
- m4udev->archdata.iommu = NULL;
- return ret;
}
static int mtk_iommu_add_device(struct device *dev)
{
+ struct dma_iommu_mapping *mtk_mapping;
struct of_phandle_args iommu_spec;
struct of_phandle_iterator it;
struct mtk_iommu_data *data;
@@ -451,15 +443,30 @@ static int mtk_iommu_add_device(struct device *dev)
if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops)
return -ENODEV; /* Not a iommu client device */
- data = dev->iommu_fwspec->iommu_priv;
- iommu_device_link(&data->iommu, dev);
-
- group = iommu_group_get_for_dev(dev);
+ /*
+ * This is a short-term bodge because the ARM DMA code doesn't
+ * understand multi-device groups, but we have to call into it
+ * successfully (and not just rely on a normal IOMMU API attach
+ * here) in order to set the correct DMA API ops on @dev.
+ */
+ group = iommu_group_alloc();
if (IS_ERR(group))
return PTR_ERR(group);
+ err = iommu_group_add_device(group, dev);
iommu_group_put(group);
- return 0;
+ if (err)
+ return err;
+
+ data = dev->iommu_fwspec->iommu_priv;
+ mtk_mapping = data->dev->archdata.iommu;
+ err = arm_iommu_attach_device(dev, mtk_mapping);
+ if (err) {
+ iommu_group_remove_device(dev);
+ return err;
+ }
+
+ return iommu_device_link(&data->iommu, dev);;
}
static void mtk_iommu_remove_device(struct device *dev)
@@ -476,24 +483,6 @@ static void mtk_iommu_remove_device(struct device *dev)
iommu_fwspec_free(dev);
}
-static struct iommu_group *mtk_iommu_device_group(struct device *dev)
-{
- struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
-
- if (!data)
- return ERR_PTR(-ENODEV);
-
- /* All the client devices are in the same m4u iommu-group */
- if (!data->m4u_group) {
- data->m4u_group = iommu_group_alloc();
- if (IS_ERR(data->m4u_group))
- dev_err(dev, "Failed to allocate M4U IOMMU group\n");
- } else {
- iommu_group_ref_get(data->m4u_group);
- }
- return data->m4u_group;
-}
-
static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
{
u32 regval;
@@ -546,7 +535,6 @@ static struct iommu_ops mtk_iommu_ops = {
.iova_to_phys = mtk_iommu_iova_to_phys,
.add_device = mtk_iommu_add_device,
.remove_device = mtk_iommu_remove_device,
- .device_group = mtk_iommu_device_group,
.pgsize_bitmap = ~0UL << MT2701_IOMMU_PAGE_SHIFT,
};
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index e135ab830ebf..c33b7b104e72 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1536,7 +1536,7 @@ static struct iommu_group *omap_iommu_device_group(struct device *dev)
struct iommu_group *group = ERR_PTR(-EINVAL);
if (arch_data->iommu_dev)
- group = arch_data->iommu_dev->group;
+ group = iommu_group_ref_get(arch_data->iommu_dev->group);
return group;
}
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 9d991c2d8767..5fc8656c60f9 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -4,6 +4,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/clk.h>
#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/device.h>
@@ -13,13 +14,15 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iommu.h>
-#include <linux/jiffies.h>
+#include <linux/iopoll.h>
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_iommu.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -36,7 +39,10 @@
#define RK_MMU_AUTO_GATING 0x24
#define DTE_ADDR_DUMMY 0xCAFEBABE
-#define FORCE_RESET_TIMEOUT 100 /* ms */
+
+#define RK_MMU_POLL_PERIOD_US 100
+#define RK_MMU_FORCE_RESET_TIMEOUT_US 100000
+#define RK_MMU_POLL_TIMEOUT_US 1000
/* RK_MMU_STATUS fields */
#define RK_MMU_STATUS_PAGING_ENABLED BIT(0)
@@ -73,11 +79,8 @@
*/
#define RK_IOMMU_PGSIZE_BITMAP 0x007ff000
-#define IOMMU_REG_POLL_COUNT_FAST 1000
-
struct rk_iommu_domain {
struct list_head iommus;
- struct platform_device *pdev;
u32 *dt; /* page directory table */
dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
@@ -86,24 +89,37 @@ struct rk_iommu_domain {
struct iommu_domain domain;
};
+/* list of clocks required by IOMMU */
+static const char * const rk_iommu_clocks[] = {
+ "aclk", "iface",
+};
+
struct rk_iommu {
struct device *dev;
void __iomem **bases;
int num_mmu;
- int *irq;
- int num_irq;
+ struct clk_bulk_data *clocks;
+ int num_clocks;
bool reset_disabled;
struct iommu_device iommu;
struct list_head node; /* entry in rk_iommu_domain.iommus */
struct iommu_domain *domain; /* domain to which iommu is attached */
+ struct iommu_group *group;
+};
+
+struct rk_iommudata {
+ struct device_link *link; /* runtime PM link from IOMMU to master */
+ struct rk_iommu *iommu;
};
+static struct device *dma_dev;
+
static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
unsigned int count)
{
size_t size = count * sizeof(u32); /* count of u32 entry */
- dma_sync_single_for_device(&dom->pdev->dev, dma, size, DMA_TO_DEVICE);
+ dma_sync_single_for_device(dma_dev, dma, size, DMA_TO_DEVICE);
}
static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -111,27 +127,6 @@ static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
return container_of(dom, struct rk_iommu_domain, domain);
}
-/**
- * Inspired by _wait_for in intel_drv.h
- * This is NOT safe for use in interrupt context.
- *
- * Note that it's important that we check the condition again after having
- * timed out, since the timeout could be due to preemption or similar and
- * we've never had a chance to check the condition before the timeout.
- */
-#define rk_wait_for(COND, MS) ({ \
- unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \
- int ret__ = 0; \
- while (!(COND)) { \
- if (time_after(jiffies, timeout__)) { \
- ret__ = (COND) ? 0 : -ETIMEDOUT; \
- break; \
- } \
- usleep_range(50, 100); \
- } \
- ret__; \
-})
-
/*
* The Rockchip rk3288 iommu uses a 2-level page table.
* The first level is the "Directory Table" (DT).
@@ -296,19 +291,21 @@ static void rk_iommu_base_command(void __iomem *base, u32 command)
{
writel(command, base + RK_MMU_COMMAND);
}
-static void rk_iommu_zap_lines(struct rk_iommu *iommu, dma_addr_t iova,
+static void rk_iommu_zap_lines(struct rk_iommu *iommu, dma_addr_t iova_start,
size_t size)
{
int i;
-
- dma_addr_t iova_end = iova + size;
+ dma_addr_t iova_end = iova_start + size;
/*
* TODO(djkurtz): Figure out when it is more efficient to shootdown the
* entire iotlb rather than iterate over individual iovas.
*/
- for (i = 0; i < iommu->num_mmu; i++)
- for (; iova < iova_end; iova += SPAGE_SIZE)
+ for (i = 0; i < iommu->num_mmu; i++) {
+ dma_addr_t iova;
+
+ for (iova = iova_start; iova < iova_end; iova += SPAGE_SIZE)
rk_iommu_write(iommu->bases[i], RK_MMU_ZAP_ONE_LINE, iova);
+ }
}
static bool rk_iommu_is_stall_active(struct rk_iommu *iommu)
@@ -335,9 +332,21 @@ static bool rk_iommu_is_paging_enabled(struct rk_iommu *iommu)
return enable;
}
+static bool rk_iommu_is_reset_done(struct rk_iommu *iommu)
+{
+ bool done = true;
+ int i;
+
+ for (i = 0; i < iommu->num_mmu; i++)
+ done &= rk_iommu_read(iommu->bases[i], RK_MMU_DTE_ADDR) == 0;
+
+ return done;
+}
+
static int rk_iommu_enable_stall(struct rk_iommu *iommu)
{
int ret, i;
+ bool val;
if (rk_iommu_is_stall_active(iommu))
return 0;
@@ -348,7 +357,9 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_STALL);
- ret = rk_wait_for(rk_iommu_is_stall_active(iommu), 1);
+ ret = readx_poll_timeout(rk_iommu_is_stall_active, iommu, val,
+ val, RK_MMU_POLL_PERIOD_US,
+ RK_MMU_POLL_TIMEOUT_US);
if (ret)
for (i = 0; i < iommu->num_mmu; i++)
dev_err(iommu->dev, "Enable stall request timed out, status: %#08x\n",
@@ -360,13 +371,16 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
static int rk_iommu_disable_stall(struct rk_iommu *iommu)
{
int ret, i;
+ bool val;
if (!rk_iommu_is_stall_active(iommu))
return 0;
rk_iommu_command(iommu, RK_MMU_CMD_DISABLE_STALL);
- ret = rk_wait_for(!rk_iommu_is_stall_active(iommu), 1);
+ ret = readx_poll_timeout(rk_iommu_is_stall_active, iommu, val,
+ !val, RK_MMU_POLL_PERIOD_US,
+ RK_MMU_POLL_TIMEOUT_US);
if (ret)
for (i = 0; i < iommu->num_mmu; i++)
dev_err(iommu->dev, "Disable stall request timed out, status: %#08x\n",
@@ -378,13 +392,16 @@ static int rk_iommu_disable_stall(struct rk_iommu *iommu)
static int rk_iommu_enable_paging(struct rk_iommu *iommu)
{
int ret, i;
+ bool val;
if (rk_iommu_is_paging_enabled(iommu))
return 0;
rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_PAGING);
- ret = rk_wait_for(rk_iommu_is_paging_enabled(iommu), 1);
+ ret = readx_poll_timeout(rk_iommu_is_paging_enabled, iommu, val,
+ val, RK_MMU_POLL_PERIOD_US,
+ RK_MMU_POLL_TIMEOUT_US);
if (ret)
for (i = 0; i < iommu->num_mmu; i++)
dev_err(iommu->dev, "Enable paging request timed out, status: %#08x\n",
@@ -396,13 +413,16 @@ static int rk_iommu_enable_paging(struct rk_iommu *iommu)
static int rk_iommu_disable_paging(struct rk_iommu *iommu)
{
int ret, i;
+ bool val;
if (!rk_iommu_is_paging_enabled(iommu))
return 0;
rk_iommu_command(iommu, RK_MMU_CMD_DISABLE_PAGING);
- ret = rk_wait_for(!rk_iommu_is_paging_enabled(iommu), 1);
+ ret = readx_poll_timeout(rk_iommu_is_paging_enabled, iommu, val,
+ !val, RK_MMU_POLL_PERIOD_US,
+ RK_MMU_POLL_TIMEOUT_US);
if (ret)
for (i = 0; i < iommu->num_mmu; i++)
dev_err(iommu->dev, "Disable paging request timed out, status: %#08x\n",
@@ -415,6 +435,7 @@ static int rk_iommu_force_reset(struct rk_iommu *iommu)
{
int ret, i;
u32 dte_addr;
+ bool val;
if (iommu->reset_disabled)
return 0;
@@ -435,13 +456,12 @@ static int rk_iommu_force_reset(struct rk_iommu *iommu)
rk_iommu_command(iommu, RK_MMU_CMD_FORCE_RESET);
- for (i = 0; i < iommu->num_mmu; i++) {
- ret = rk_wait_for(rk_iommu_read(iommu->bases[i], RK_MMU_DTE_ADDR) == 0x00000000,
- FORCE_RESET_TIMEOUT);
- if (ret) {
- dev_err(iommu->dev, "FORCE_RESET command timed out\n");
- return ret;
- }
+ ret = readx_poll_timeout(rk_iommu_is_reset_done, iommu, val,
+ val, RK_MMU_FORCE_RESET_TIMEOUT_US,
+ RK_MMU_POLL_TIMEOUT_US);
+ if (ret) {
+ dev_err(iommu->dev, "FORCE_RESET command timed out\n");
+ return ret;
}
return 0;
@@ -503,6 +523,12 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
irqreturn_t ret = IRQ_NONE;
int i;
+ if (WARN_ON(!pm_runtime_get_if_in_use(iommu->dev)))
+ return 0;
+
+ if (WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks)))
+ goto out;
+
for (i = 0; i < iommu->num_mmu; i++) {
int_status = rk_iommu_read(iommu->bases[i], RK_MMU_INT_STATUS);
if (int_status == 0)
@@ -549,6 +575,10 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
rk_iommu_write(iommu->bases[i], RK_MMU_INT_CLEAR, int_status);
}
+ clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+
+out:
+ pm_runtime_put(iommu->dev);
return ret;
}
@@ -590,8 +620,17 @@ static void rk_iommu_zap_iova(struct rk_iommu_domain *rk_domain,
spin_lock_irqsave(&rk_domain->iommus_lock, flags);
list_for_each(pos, &rk_domain->iommus) {
struct rk_iommu *iommu;
+
iommu = list_entry(pos, struct rk_iommu, node);
- rk_iommu_zap_lines(iommu, iova, size);
+
+ /* Only zap TLBs of IOMMUs that are powered on. */
+ if (pm_runtime_get_if_in_use(iommu->dev)) {
+ WARN_ON(clk_bulk_enable(iommu->num_clocks,
+ iommu->clocks));
+ rk_iommu_zap_lines(iommu, iova, size);
+ clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+ pm_runtime_put(iommu->dev);
+ }
}
spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
}
@@ -608,7 +647,6 @@ static void rk_iommu_zap_iova_first_last(struct rk_iommu_domain *rk_domain,
static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain,
dma_addr_t iova)
{
- struct device *dev = &rk_domain->pdev->dev;
u32 *page_table, *dte_addr;
u32 dte_index, dte;
phys_addr_t pt_phys;
@@ -626,9 +664,9 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);
- pt_dma = dma_map_single(dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
- if (dma_mapping_error(dev, pt_dma)) {
- dev_err(dev, "DMA mapping error while allocating page table\n");
+ pt_dma = dma_map_single(dma_dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
+ if (dma_mapping_error(dma_dev, pt_dma)) {
+ dev_err(dma_dev, "DMA mapping error while allocating page table\n");
free_page((unsigned long)page_table);
return ERR_PTR(-ENOMEM);
}
@@ -790,52 +828,46 @@ static size_t rk_iommu_unmap(struct iommu_domain *domain, unsigned long _iova,
static struct rk_iommu *rk_iommu_from_dev(struct device *dev)
{
- struct iommu_group *group;
- struct device *iommu_dev;
- struct rk_iommu *rk_iommu;
+ struct rk_iommudata *data = dev->archdata.iommu;
- group = iommu_group_get(dev);
- if (!group)
- return NULL;
- iommu_dev = iommu_group_get_iommudata(group);
- rk_iommu = dev_get_drvdata(iommu_dev);
- iommu_group_put(group);
+ return data ? data->iommu : NULL;
+}
+
+/* Must be called with iommu powered on and attached */
+static void rk_iommu_disable(struct rk_iommu *iommu)
+{
+ int i;
- return rk_iommu;
+ /* Ignore error while disabling, just keep going */
+ WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks));
+ rk_iommu_enable_stall(iommu);
+ rk_iommu_disable_paging(iommu);
+ for (i = 0; i < iommu->num_mmu; i++) {
+ rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, 0);
+ rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, 0);
+ }
+ rk_iommu_disable_stall(iommu);
+ clk_bulk_disable(iommu->num_clocks, iommu->clocks);
}
-static int rk_iommu_attach_device(struct iommu_domain *domain,
- struct device *dev)
+/* Must be called with iommu powered on and attached */
+static int rk_iommu_enable(struct rk_iommu *iommu)
{
- struct rk_iommu *iommu;
+ struct iommu_domain *domain = iommu->domain;
struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
- unsigned long flags;
int ret, i;
- /*
- * Allow 'virtual devices' (e.g., drm) to attach to domain.
- * Such a device does not belong to an iommu group.
- */
- iommu = rk_iommu_from_dev(dev);
- if (!iommu)
- return 0;
+ ret = clk_bulk_enable(iommu->num_clocks, iommu->clocks);
+ if (ret)
+ return ret;
ret = rk_iommu_enable_stall(iommu);
if (ret)
- return ret;
+ goto out_disable_clocks;
ret = rk_iommu_force_reset(iommu);
if (ret)
- return ret;
-
- iommu->domain = domain;
-
- for (i = 0; i < iommu->num_irq; i++) {
- ret = devm_request_irq(iommu->dev, iommu->irq[i], rk_iommu_irq,
- IRQF_SHARED, dev_name(dev), iommu);
- if (ret)
- return ret;
- }
+ goto out_disable_stall;
for (i = 0; i < iommu->num_mmu; i++) {
rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR,
@@ -845,18 +877,12 @@ static int rk_iommu_attach_device(struct iommu_domain *domain,
}
ret = rk_iommu_enable_paging(iommu);
- if (ret)
- return ret;
-
- spin_lock_irqsave(&rk_domain->iommus_lock, flags);
- list_add_tail(&iommu->node, &rk_domain->iommus);
- spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
-
- dev_dbg(dev, "Attached to iommu domain\n");
+out_disable_stall:
rk_iommu_disable_stall(iommu);
-
- return 0;
+out_disable_clocks:
+ clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+ return ret;
}
static void rk_iommu_detach_device(struct iommu_domain *domain,
@@ -865,60 +891,90 @@ static void rk_iommu_detach_device(struct iommu_domain *domain,
struct rk_iommu *iommu;
struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
unsigned long flags;
- int i;
/* Allow 'virtual devices' (eg drm) to detach from domain */
iommu = rk_iommu_from_dev(dev);
if (!iommu)
return;
+ dev_dbg(dev, "Detaching from iommu domain\n");
+
+ /* iommu already detached */
+ if (iommu->domain != domain)
+ return;
+
+ iommu->domain = NULL;
+
spin_lock_irqsave(&rk_domain->iommus_lock, flags);
list_del_init(&iommu->node);
spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
- /* Ignore error while disabling, just keep going */
- rk_iommu_enable_stall(iommu);
- rk_iommu_disable_paging(iommu);
- for (i = 0; i < iommu->num_mmu; i++) {
- rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, 0);
- rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, 0);
+ if (pm_runtime_get_if_in_use(iommu->dev)) {
+ rk_iommu_disable(iommu);
+ pm_runtime_put(iommu->dev);
}
- rk_iommu_disable_stall(iommu);
+}
- for (i = 0; i < iommu->num_irq; i++)
- devm_free_irq(iommu->dev, iommu->irq[i], iommu);
+static int rk_iommu_attach_device(struct iommu_domain *domain,
+ struct device *dev)
+{
+ struct rk_iommu *iommu;
+ struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
+ unsigned long flags;
+ int ret;
- iommu->domain = NULL;
+ /*
+ * Allow 'virtual devices' (e.g., drm) to attach to domain.
+ * Such a device does not belong to an iommu group.
+ */
+ iommu = rk_iommu_from_dev(dev);
+ if (!iommu)
+ return 0;
+
+ dev_dbg(dev, "Attaching to iommu domain\n");
+
+ /* iommu already attached */
+ if (iommu->domain == domain)
+ return 0;
- dev_dbg(dev, "Detached from iommu domain\n");
+ if (iommu->domain)
+ rk_iommu_detach_device(iommu->domain, dev);
+
+ iommu->domain = domain;
+
+ spin_lock_irqsave(&rk_domain->iommus_lock, flags);
+ list_add_tail(&iommu->node, &rk_domain->iommus);
+ spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
+
+ if (!pm_runtime_get_if_in_use(iommu->dev))
+ return 0;
+
+ ret = rk_iommu_enable(iommu);
+ if (ret)
+ rk_iommu_detach_device(iommu->domain, dev);
+
+ pm_runtime_put(iommu->dev);
+
+ return ret;
}
static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)
{
struct rk_iommu_domain *rk_domain;
- struct platform_device *pdev;
- struct device *iommu_dev;
if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
return NULL;
- /* Register a pdev per domain, so DMA API can base on this *dev
- * even some virtual master doesn't have an iommu slave
- */
- pdev = platform_device_register_simple("rk_iommu_domain",
- PLATFORM_DEVID_AUTO, NULL, 0);
- if (IS_ERR(pdev))
+ if (!dma_dev)
return NULL;
- rk_domain = devm_kzalloc(&pdev->dev, sizeof(*rk_domain), GFP_KERNEL);
+ rk_domain = devm_kzalloc(dma_dev, sizeof(*rk_domain), GFP_KERNEL);
if (!rk_domain)
- goto err_unreg_pdev;
-
- rk_domain->pdev = pdev;
+ return NULL;
if (type == IOMMU_DOMAIN_DMA &&
iommu_get_dma_cookie(&rk_domain->domain))
- goto err_unreg_pdev;
+ return NULL;
/*
* rk32xx iommus use a 2 level pagetable.
@@ -929,11 +985,10 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)
if (!rk_domain->dt)
goto err_put_cookie;
- iommu_dev = &pdev->dev;
- rk_domain->dt_dma = dma_map_single(iommu_dev, rk_domain->dt,
+ rk_domain->dt_dma = dma_map_single(dma_dev, rk_domain->dt,
SPAGE_SIZE, DMA_TO_DEVICE);
- if (dma_mapping_error(iommu_dev, rk_domain->dt_dma)) {
- dev_err(iommu_dev, "DMA map error for DT\n");
+ if (dma_mapping_error(dma_dev, rk_domain->dt_dma)) {
+ dev_err(dma_dev, "DMA map error for DT\n");
goto err_free_dt;
}
@@ -954,8 +1009,6 @@ err_free_dt:
err_put_cookie:
if (type == IOMMU_DOMAIN_DMA)
iommu_put_dma_cookie(&rk_domain->domain);
-err_unreg_pdev:
- platform_device_unregister(pdev);
return NULL;
}
@@ -972,126 +1025,82 @@ static void rk_iommu_domain_free(struct iommu_domain *domain)
if (rk_dte_is_pt_valid(dte)) {
phys_addr_t pt_phys = rk_dte_pt_address(dte);
u32 *page_table = phys_to_virt(pt_phys);
- dma_unmap_single(&rk_domain->pdev->dev, pt_phys,
+ dma_unmap_single(dma_dev, pt_phys,
SPAGE_SIZE, DMA_TO_DEVICE);
free_page((unsigned long)page_table);
}
}
- dma_unmap_single(&rk_domain->pdev->dev, rk_domain->dt_dma,
+ dma_unmap_single(dma_dev, rk_domain->dt_dma,
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);
-
- platform_device_unregister(rk_domain->pdev);
}
-static bool rk_iommu_is_dev_iommu_master(struct device *dev)
+static int rk_iommu_add_device(struct device *dev)
{
- struct device_node *np = dev->of_node;
- int ret;
-
- /*
- * An iommu master has an iommus property containing a list of phandles
- * to iommu nodes, each with an #iommu-cells property with value 0.
- */
- ret = of_count_phandle_with_args(np, "iommus", "#iommu-cells");
- return (ret > 0);
-}
+ struct iommu_group *group;
+ struct rk_iommu *iommu;
+ struct rk_iommudata *data;
-static int rk_iommu_group_set_iommudata(struct iommu_group *group,
- struct device *dev)
-{
- struct device_node *np = dev->of_node;
- struct platform_device *pd;
- int ret;
- struct of_phandle_args args;
+ data = dev->archdata.iommu;
+ if (!data)
+ return -ENODEV;
- /*
- * An iommu master has an iommus property containing a list of phandles
- * to iommu nodes, each with an #iommu-cells property with value 0.
- */
- ret = of_parse_phandle_with_args(np, "iommus", "#iommu-cells", 0,
- &args);
- if (ret) {
- dev_err(dev, "of_parse_phandle_with_args(%pOF) => %d\n",
- np, ret);
- return ret;
- }
- if (args.args_count != 0) {
- dev_err(dev, "incorrect number of iommu params found for %pOF (found %d, expected 0)\n",
- args.np, args.args_count);
- return -EINVAL;
- }
+ iommu = rk_iommu_from_dev(dev);
- pd = of_find_device_by_node(args.np);
- of_node_put(args.np);
- if (!pd) {
- dev_err(dev, "iommu %pOF not found\n", args.np);
- return -EPROBE_DEFER;
- }
+ group = iommu_group_get_for_dev(dev);
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+ iommu_group_put(group);
- /* TODO(djkurtz): handle multiple slave iommus for a single master */
- iommu_group_set_iommudata(group, &pd->dev, NULL);
+ iommu_device_link(&iommu->iommu, dev);
+ data->link = device_link_add(dev, iommu->dev, DL_FLAG_PM_RUNTIME);
return 0;
}
-static int rk_iommu_add_device(struct device *dev)
+static void rk_iommu_remove_device(struct device *dev)
{
- struct iommu_group *group;
struct rk_iommu *iommu;
- int ret;
-
- if (!rk_iommu_is_dev_iommu_master(dev))
- return -ENODEV;
+ struct rk_iommudata *data = dev->archdata.iommu;
- group = iommu_group_get(dev);
- if (!group) {
- group = iommu_group_alloc();
- if (IS_ERR(group)) {
- dev_err(dev, "Failed to allocate IOMMU group\n");
- return PTR_ERR(group);
- }
- }
+ iommu = rk_iommu_from_dev(dev);
- ret = iommu_group_add_device(group, dev);
- if (ret)
- goto err_put_group;
+ device_link_del(data->link);
+ iommu_device_unlink(&iommu->iommu, dev);
+ iommu_group_remove_device(dev);
+}
- ret = rk_iommu_group_set_iommudata(group, dev);
- if (ret)
- goto err_remove_device;
+static struct iommu_group *rk_iommu_device_group(struct device *dev)
+{
+ struct rk_iommu *iommu;
iommu = rk_iommu_from_dev(dev);
- if (iommu)
- iommu_device_link(&iommu->iommu, dev);
-
- iommu_group_put(group);
-
- return 0;
-err_remove_device:
- iommu_group_remove_device(dev);
-err_put_group:
- iommu_group_put(group);
- return ret;
+ return iommu_group_ref_get(iommu->group);
}
-static void rk_iommu_remove_device(struct device *dev)
+static int rk_iommu_of_xlate(struct device *dev,
+ struct of_phandle_args *args)
{
- struct rk_iommu *iommu;
+ struct platform_device *iommu_dev;
+ struct rk_iommudata *data;
- if (!rk_iommu_is_dev_iommu_master(dev))
- return;
+ data = devm_kzalloc(dma_dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- iommu = rk_iommu_from_dev(dev);
- if (iommu)
- iommu_device_unlink(&iommu->iommu, dev);
+ iommu_dev = of_find_device_by_node(args->np);
- iommu_group_remove_device(dev);
+ data->iommu = platform_get_drvdata(iommu_dev);
+ dev->archdata.iommu = data;
+
+ of_dev_put(iommu_dev);
+
+ return 0;
}
static const struct iommu_ops rk_iommu_ops = {
@@ -1105,31 +1114,9 @@ static const struct iommu_ops rk_iommu_ops = {
.add_device = rk_iommu_add_device,
.remove_device = rk_iommu_remove_device,
.iova_to_phys = rk_iommu_iova_to_phys,
+ .device_group = rk_iommu_device_group,
.pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
-};
-
-static int rk_iommu_domain_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
-
- dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);
- if (!dev->dma_parms)
- return -ENOMEM;
-
- /* Set dma_ops for dev, otherwise it would be dummy_dma_ops */
- arch_setup_dma_ops(dev, 0, DMA_BIT_MASK(32), NULL, false);
-
- dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
- dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
-
- return 0;
-}
-
-static struct platform_driver rk_iommu_domain_driver = {
- .probe = rk_iommu_domain_probe,
- .driver = {
- .name = "rk_iommu_domain",
- },
+ .of_xlate = rk_iommu_of_xlate,
};
static int rk_iommu_probe(struct platform_device *pdev)
@@ -1138,7 +1125,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
struct rk_iommu *iommu;
struct resource *res;
int num_res = pdev->num_resources;
- int err, i;
+ int err, i, irq;
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
if (!iommu)
@@ -1165,50 +1152,108 @@ static int rk_iommu_probe(struct platform_device *pdev)
if (iommu->num_mmu == 0)
return PTR_ERR(iommu->bases[0]);
- iommu->num_irq = platform_irq_count(pdev);
- if (iommu->num_irq < 0)
- return iommu->num_irq;
- if (iommu->num_irq == 0)
- return -ENXIO;
-
- iommu->irq = devm_kcalloc(dev, iommu->num_irq, sizeof(*iommu->irq),
- GFP_KERNEL);
- if (!iommu->irq)
- return -ENOMEM;
+ i = 0;
+ while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) {
+ if (irq < 0)
+ return irq;
- for (i = 0; i < iommu->num_irq; i++) {
- iommu->irq[i] = platform_get_irq(pdev, i);
- if (iommu->irq[i] < 0) {
- dev_err(dev, "Failed to get IRQ, %d\n", iommu->irq[i]);
- return -ENXIO;
- }
+ err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
+ IRQF_SHARED, dev_name(dev), iommu);
+ if (err)
+ return err;
}
iommu->reset_disabled = device_property_read_bool(dev,
"rockchip,disable-mmu-reset");
- err = iommu_device_sysfs_add(&iommu->iommu, dev, NULL, dev_name(dev));
+ iommu->num_clocks = ARRAY_SIZE(rk_iommu_clocks);
+ iommu->clocks = devm_kcalloc(iommu->dev, iommu->num_clocks,
+ sizeof(*iommu->clocks), GFP_KERNEL);
+ if (!iommu->clocks)
+ return -ENOMEM;
+
+ for (i = 0; i < iommu->num_clocks; ++i)
+ iommu->clocks[i].id = rk_iommu_clocks[i];
+
+ err = devm_clk_bulk_get(iommu->dev, iommu->num_clocks, iommu->clocks);
+ if (err)
+ return err;
+
+ err = clk_bulk_prepare(iommu->num_clocks, iommu->clocks);
if (err)
return err;
+ iommu->group = iommu_group_alloc();
+ if (IS_ERR(iommu->group)) {
+ err = PTR_ERR(iommu->group);
+ goto err_unprepare_clocks;
+ }
+
+ err = iommu_device_sysfs_add(&iommu->iommu, dev, NULL, dev_name(dev));
+ if (err)
+ goto err_put_group;
+
iommu_device_set_ops(&iommu->iommu, &rk_iommu_ops);
+ iommu_device_set_fwnode(&iommu->iommu, &dev->of_node->fwnode);
+
err = iommu_device_register(&iommu->iommu);
+ if (err)
+ goto err_remove_sysfs;
+
+ /*
+ * Use the first registered IOMMU device for domain to use with DMA
+ * API, since a domain might not physically correspond to a single
+ * IOMMU device..
+ */
+ if (!dma_dev)
+ dma_dev = &pdev->dev;
+
+ bus_set_iommu(&platform_bus_type, &rk_iommu_ops);
+ pm_runtime_enable(dev);
+
+ return 0;
+err_remove_sysfs:
+ iommu_device_sysfs_remove(&iommu->iommu);
+err_put_group:
+ iommu_group_put(iommu->group);
+err_unprepare_clocks:
+ clk_bulk_unprepare(iommu->num_clocks, iommu->clocks);
return err;
}
-static int rk_iommu_remove(struct platform_device *pdev)
+static void rk_iommu_shutdown(struct platform_device *pdev)
{
- struct rk_iommu *iommu = platform_get_drvdata(pdev);
+ pm_runtime_force_suspend(&pdev->dev);
+}
- if (iommu) {
- iommu_device_sysfs_remove(&iommu->iommu);
- iommu_device_unregister(&iommu->iommu);
- }
+static int __maybe_unused rk_iommu_suspend(struct device *dev)
+{
+ struct rk_iommu *iommu = dev_get_drvdata(dev);
+ if (!iommu->domain)
+ return 0;
+
+ rk_iommu_disable(iommu);
return 0;
}
+static int __maybe_unused rk_iommu_resume(struct device *dev)
+{
+ struct rk_iommu *iommu = dev_get_drvdata(dev);
+
+ if (!iommu->domain)
+ return 0;
+
+ return rk_iommu_enable(iommu);
+}
+
+static const struct dev_pm_ops rk_iommu_pm_ops = {
+ SET_RUNTIME_PM_OPS(rk_iommu_suspend, rk_iommu_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+};
+
static const struct of_device_id rk_iommu_dt_ids[] = {
{ .compatible = "rockchip,iommu" },
{ /* sentinel */ }
@@ -1217,45 +1262,22 @@ MODULE_DEVICE_TABLE(of, rk_iommu_dt_ids);
static struct platform_driver rk_iommu_driver = {
.probe = rk_iommu_probe,
- .remove = rk_iommu_remove,
+ .shutdown = rk_iommu_shutdown,
.driver = {
.name = "rk_iommu",
.of_match_table = rk_iommu_dt_ids,
+ .pm = &rk_iommu_pm_ops,
+ .suppress_bind_attrs = true,
},
};
static int __init rk_iommu_init(void)
{
- struct device_node *np;
- int ret;
-
- np = of_find_matching_node(NULL, rk_iommu_dt_ids);
- if (!np)
- return 0;
-
- of_node_put(np);
-
- ret = bus_set_iommu(&platform_bus_type, &rk_iommu_ops);
- if (ret)
- return ret;
-
- ret = platform_driver_register(&rk_iommu_domain_driver);
- if (ret)
- return ret;
-
- ret = platform_driver_register(&rk_iommu_driver);
- if (ret)
- platform_driver_unregister(&rk_iommu_domain_driver);
- return ret;
+ return platform_driver_register(&rk_iommu_driver);
}
-static void __exit rk_iommu_exit(void)
-{
- platform_driver_unregister(&rk_iommu_driver);
- platform_driver_unregister(&rk_iommu_domain_driver);
-}
-
subsys_initcall(rk_iommu_init);
-module_exit(rk_iommu_exit);
+
+IOMMU_OF_DECLARE(rk_iommu_of, "rockchip,iommu");
MODULE_DESCRIPTION("IOMMU API for Rockchip");
MODULE_AUTHOR("Simon Xue <xxm@rock-chips.com> and Daniel Kurtz <djkurtz@chromium.org>");
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 2982e93d2369..5416f2b2ac21 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3612,7 +3612,8 @@ static int __init gic_acpi_parse_madt_its(struct acpi_subtable_header *header,
return -ENOMEM;
}
- err = iort_register_domain_token(its_entry->translation_id, dom_handle);
+ err = iort_register_domain_token(its_entry->translation_id, res.start,
+ dom_handle);
if (err) {
pr_err("ITS@%pa: Unable to register GICv3 ITS domain token (ITS ID %d) to IORT\n",
&res.start, its_entry->translation_id);
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 2c8ac3688815..edff083f7c4e 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -201,7 +201,7 @@ config BLK_DEV_DM_BUILTIN
config BLK_DEV_DM
tristate "Device mapper support"
select BLK_DEV_DM_BUILTIN
- select DAX
+ depends on DAX || DAX=n
---help---
Device-mapper is a low level volume manager. It works by allowing
people to specify mappings for ranges of logical sectors. Various
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 99297212eeec..775c06d953b7 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -154,6 +154,7 @@ static int linear_iterate_devices(struct dm_target *ti,
return fn(ti, lc->dev, lc->start, ti->len, data);
}
+#if IS_ENABLED(CONFIG_DAX_DRIVER)
static long linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
{
@@ -184,6 +185,11 @@ static size_t linear_dax_copy_from_iter(struct dm_target *ti, pgoff_t pgoff,
return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i);
}
+#else
+#define linear_dax_direct_access NULL
+#define linear_dax_copy_from_iter NULL
+#endif
+
static struct target_type linear_target = {
.name = "linear",
.version = {1, 4, 0},
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index 9de072b7782a..c90c7c08a77f 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -611,51 +611,6 @@ static int log_mark(struct log_writes_c *lc, char *data)
return 0;
}
-static int log_dax(struct log_writes_c *lc, sector_t sector, size_t bytes,
- struct iov_iter *i)
-{
- struct pending_block *block;
-
- if (!bytes)
- return 0;
-
- block = kzalloc(sizeof(struct pending_block), GFP_KERNEL);
- if (!block) {
- DMERR("Error allocating dax pending block");
- return -ENOMEM;
- }
-
- block->data = kzalloc(bytes, GFP_KERNEL);
- if (!block->data) {
- DMERR("Error allocating dax data space");
- kfree(block);
- return -ENOMEM;
- }
-
- /* write data provided via the iterator */
- if (!copy_from_iter(block->data, bytes, i)) {
- DMERR("Error copying dax data");
- kfree(block->data);
- kfree(block);
- return -EIO;
- }
-
- /* rewind the iterator so that the block driver can use it */
- iov_iter_revert(i, bytes);
-
- block->datalen = bytes;
- block->sector = bio_to_dev_sectors(lc, sector);
- block->nr_sectors = ALIGN(bytes, lc->sectorsize) >> lc->sectorshift;
-
- atomic_inc(&lc->pending_blocks);
- spin_lock_irq(&lc->blocks_lock);
- list_add_tail(&block->list, &lc->unflushed_blocks);
- spin_unlock_irq(&lc->blocks_lock);
- wake_up_process(lc->log_kthread);
-
- return 0;
-}
-
static void log_writes_dtr(struct dm_target *ti)
{
struct log_writes_c *lc = ti->private;
@@ -925,6 +880,52 @@ static void log_writes_io_hints(struct dm_target *ti, struct queue_limits *limit
limits->io_min = limits->physical_block_size;
}
+#if IS_ENABLED(CONFIG_DAX_DRIVER)
+static int log_dax(struct log_writes_c *lc, sector_t sector, size_t bytes,
+ struct iov_iter *i)
+{
+ struct pending_block *block;
+
+ if (!bytes)
+ return 0;
+
+ block = kzalloc(sizeof(struct pending_block), GFP_KERNEL);
+ if (!block) {
+ DMERR("Error allocating dax pending block");
+ return -ENOMEM;
+ }
+
+ block->data = kzalloc(bytes, GFP_KERNEL);
+ if (!block->data) {
+ DMERR("Error allocating dax data space");
+ kfree(block);
+ return -ENOMEM;
+ }
+
+ /* write data provided via the iterator */
+ if (!copy_from_iter(block->data, bytes, i)) {
+ DMERR("Error copying dax data");
+ kfree(block->data);
+ kfree(block);
+ return -EIO;
+ }
+
+ /* rewind the iterator so that the block driver can use it */
+ iov_iter_revert(i, bytes);
+
+ block->datalen = bytes;
+ block->sector = bio_to_dev_sectors(lc, sector);
+ block->nr_sectors = ALIGN(bytes, lc->sectorsize) >> lc->sectorshift;
+
+ atomic_inc(&lc->pending_blocks);
+ spin_lock_irq(&lc->blocks_lock);
+ list_add_tail(&block->list, &lc->unflushed_blocks);
+ spin_unlock_irq(&lc->blocks_lock);
+ wake_up_process(lc->log_kthread);
+
+ return 0;
+}
+
static long log_writes_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
{
@@ -961,6 +962,10 @@ static size_t log_writes_dax_copy_from_iter(struct dm_target *ti,
dax_copy:
return dax_copy_from_iter(lc->dev->dax_dev, pgoff, addr, bytes, i);
}
+#else
+#define log_writes_dax_direct_access NULL
+#define log_writes_dax_copy_from_iter NULL
+#endif
static struct target_type log_writes_target = {
.name = "log-writes",
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index bb907cb3e60d..fe7fb9b1aec3 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -313,6 +313,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio)
return DM_MAPIO_REMAPPED;
}
+#if IS_ENABLED(CONFIG_DAX_DRIVER)
static long stripe_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
{
@@ -353,6 +354,11 @@ static size_t stripe_dax_copy_from_iter(struct dm_target *ti, pgoff_t pgoff,
return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i);
}
+#else
+#define stripe_dax_direct_access NULL
+#define stripe_dax_copy_from_iter NULL
+#endif
+
/*
* Stripe status:
*
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 5a81c47be4e4..4ea404dbcf0b 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1826,7 +1826,7 @@ static void cleanup_mapped_device(struct mapped_device *md)
static struct mapped_device *alloc_dev(int minor)
{
int r, numa_node_id = dm_get_numa_node();
- struct dax_device *dax_dev;
+ struct dax_device *dax_dev = NULL;
struct mapped_device *md;
void *old_md;
@@ -1892,9 +1892,11 @@ static struct mapped_device *alloc_dev(int minor)
md->disk->private_data = md;
sprintf(md->disk->disk_name, "dm-%d", minor);
- dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops);
- if (!dax_dev)
- goto bad;
+ if (IS_ENABLED(CONFIG_DAX_DRIVER)) {
+ dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops);
+ if (!dax_dev)
+ goto bad;
+ }
md->dax_dev = dax_dev;
add_disk_no_queue_reg(md->disk);
diff --git a/drivers/media/cec/cec-pin.c b/drivers/media/cec/cec-pin.c
index fafe1ebc8aff..2a5df99735fa 100644
--- a/drivers/media/cec/cec-pin.c
+++ b/drivers/media/cec/cec-pin.c
@@ -668,7 +668,7 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts)
/* Start bit low is too short, go back to idle */
if (delta < CEC_TIM_START_BIT_LOW_MIN - CEC_TIM_IDLE_SAMPLE) {
if (!pin->rx_start_bit_low_too_short_cnt++) {
- pin->rx_start_bit_low_too_short_ts = pin->ts;
+ pin->rx_start_bit_low_too_short_ts = ktime_to_ns(pin->ts);
pin->rx_start_bit_low_too_short_delta = delta;
}
cec_pin_to_idle(pin);
@@ -700,7 +700,7 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts)
/* Start bit is too short, go back to idle */
if (delta < CEC_TIM_START_BIT_TOTAL_MIN - CEC_TIM_IDLE_SAMPLE) {
if (!pin->rx_start_bit_too_short_cnt++) {
- pin->rx_start_bit_too_short_ts = pin->ts;
+ pin->rx_start_bit_too_short_ts = ktime_to_ns(pin->ts);
pin->rx_start_bit_too_short_delta = delta;
}
cec_pin_to_idle(pin);
@@ -770,7 +770,7 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts)
*/
if (delta < CEC_TIM_DATA_BIT_TOTAL_MIN) {
if (!pin->rx_data_bit_too_short_cnt++) {
- pin->rx_data_bit_too_short_ts = pin->ts;
+ pin->rx_data_bit_too_short_ts = ktime_to_ns(pin->ts);
pin->rx_data_bit_too_short_delta = delta;
}
cec_pin_low(pin);
diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
index 37632bc524d4..9b64f4f354bf 100644
--- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
+++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
@@ -1149,7 +1149,7 @@ static void gen_twopix(struct tpg_data *tpg,
case V4L2_PIX_FMT_NV42:
buf[0][offset] = r_y_h;
buf[1][2 * offset] = b_v;
- buf[1][(2 * offset + 1) %8] = g_u_s;
+ buf[1][(2 * offset + 1) % 8] = g_u_s;
break;
case V4L2_PIX_FMT_YUYV:
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 21a7d4b47e1a..e33414975065 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -2089,7 +2089,7 @@ static int dvb_frontend_handle_compat_ioctl(struct file *file, unsigned int cmd,
}
for (i = 0; i < tvps->num; i++) {
err = dtv_property_process_get(
- fe, &getp, (struct dtv_property *)tvp + i, file);
+ fe, &getp, (struct dtv_property *)(tvp + i), file);
if (err < 0) {
kfree(tvp);
return err;
diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c b/drivers/media/i2c/adv748x/adv748x-afe.c
index 5188178588c9..61514bae7e5c 100644
--- a/drivers/media/i2c/adv748x/adv748x-afe.c
+++ b/drivers/media/i2c/adv748x/adv748x-afe.c
@@ -275,7 +275,8 @@ static int adv748x_afe_s_stream(struct v4l2_subdev *sd, int enable)
{
struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
struct adv748x_state *state = adv748x_afe_to_state(afe);
- int ret, signal = V4L2_IN_ST_NO_SIGNAL;
+ u32 signal = V4L2_IN_ST_NO_SIGNAL;
+ int ret;
mutex_lock(&state->mutex);
diff --git a/drivers/media/i2c/dw9714.c b/drivers/media/i2c/dw9714.c
index 8dbbf0f917df..91fae01d052b 100644
--- a/drivers/media/i2c/dw9714.c
+++ b/drivers/media/i2c/dw9714.c
@@ -1,15 +1,5 @@
-/*
- * Copyright (c) 2015--2017 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2015--2017 Intel Corporation.
#include <linux/delay.h>
#include <linux/i2c.h>
diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c
index 664e8acdf2a0..daec33f4196a 100644
--- a/drivers/media/i2c/imx274.c
+++ b/drivers/media/i2c/imx274.c
@@ -1426,7 +1426,7 @@ static int imx274_set_vflip(struct stimx274 *priv, int val)
err = imx274_write_reg(priv, IMX274_VFLIP_REG, val);
if (err) {
- dev_err(&priv->client->dev, "VFILP control error\n");
+ dev_err(&priv->client->dev, "VFLIP control error\n");
return err;
}
diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c
index 30ee9f71bf0d..3dbcae257164 100644
--- a/drivers/media/i2c/ov13858.c
+++ b/drivers/media/i2c/ov13858.c
@@ -1,16 +1,5 @@
-/*
- * Copyright (c) 2017 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017 Intel Corporation.
#include <linux/acpi.h>
#include <linux/i2c.h>
@@ -1375,7 +1364,9 @@ ov13858_set_pad_format(struct v4l2_subdev *sd,
if (fmt->format.code != MEDIA_BUS_FMT_SGRBG10_1X10)
fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
- mode = v4l2_find_nearest_size(supported_modes, width, height,
+ mode = v4l2_find_nearest_size(supported_modes,
+ ARRAY_SIZE(supported_modes),
+ width, height,
fmt->format.width, fmt->format.height);
ov13858_update_pad_format(mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
diff --git a/drivers/media/i2c/ov2685.c b/drivers/media/i2c/ov2685.c
index 83c55e8288e7..385c1886a947 100644
--- a/drivers/media/i2c/ov2685.c
+++ b/drivers/media/i2c/ov2685.c
@@ -832,7 +832,6 @@ MODULE_DEVICE_TABLE(of, ov2685_of_match);
static struct i2c_driver ov2685_i2c_driver = {
.driver = {
.name = "ov2685",
- .owner = THIS_MODULE,
.pm = &ov2685_pm_ops,
.of_match_table = of_match_ptr(ov2685_of_match),
},
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 03940f0cdfa6..852026baa2e7 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -1641,6 +1641,9 @@ static int ov5640_set_mode(struct ov5640_dev *sensor,
return 0;
}
+static int ov5640_set_framefmt(struct ov5640_dev *sensor,
+ struct v4l2_mbus_framefmt *format);
+
/* restore the last set video mode after chip power-on */
static int ov5640_restore_mode(struct ov5640_dev *sensor)
{
@@ -1652,7 +1655,11 @@ static int ov5640_restore_mode(struct ov5640_dev *sensor)
return ret;
/* now restore the last capture mode */
- return ov5640_set_mode(sensor, &ov5640_mode_init_data);
+ ret = ov5640_set_mode(sensor, &ov5640_mode_init_data);
+ if (ret < 0)
+ return ret;
+
+ return ov5640_set_framefmt(sensor, &sensor->fmt);
}
static void ov5640_power(struct ov5640_dev *sensor, bool enable)
@@ -1874,7 +1881,13 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
if (ov5640_formats[i].code == fmt->code)
break;
if (i >= ARRAY_SIZE(ov5640_formats))
- fmt->code = ov5640_formats[0].code;
+ i = 0;
+
+ fmt->code = ov5640_formats[i].code;
+ fmt->colorspace = ov5640_formats[i].colorspace;
+ fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
+ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+ fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
return 0;
}
@@ -1885,6 +1898,7 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
{
struct ov5640_dev *sensor = to_ov5640_dev(sd);
const struct ov5640_mode_info *new_mode;
+ struct v4l2_mbus_framefmt *mbus_fmt = &format->format;
int ret;
if (format->pad != 0)
@@ -1897,7 +1911,7 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
goto out;
}
- ret = ov5640_try_fmt_internal(sd, &format->format,
+ ret = ov5640_try_fmt_internal(sd, mbus_fmt,
sensor->current_fr, &new_mode);
if (ret)
goto out;
@@ -1906,12 +1920,12 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt =
v4l2_subdev_get_try_format(sd, cfg, 0);
- *fmt = format->format;
+ *fmt = *mbus_fmt;
goto out;
}
sensor->current_mode = new_mode;
- sensor->fmt = format->format;
+ sensor->fmt = *mbus_fmt;
sensor->pending_mode_change = true;
out:
mutex_unlock(&sensor->lock);
@@ -2496,6 +2510,7 @@ static int ov5640_probe(struct i2c_client *client,
struct device *dev = &client->dev;
struct fwnode_handle *endpoint;
struct ov5640_dev *sensor;
+ struct v4l2_mbus_framefmt *fmt;
int ret;
sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
@@ -2503,10 +2518,15 @@ static int ov5640_probe(struct i2c_client *client,
return -ENOMEM;
sensor->i2c_client = client;
- sensor->fmt.code = MEDIA_BUS_FMT_UYVY8_2X8;
- sensor->fmt.width = 640;
- sensor->fmt.height = 480;
- sensor->fmt.field = V4L2_FIELD_NONE;
+ fmt = &sensor->fmt;
+ fmt->code = ov5640_formats[0].code;
+ fmt->colorspace = ov5640_formats[0].colorspace;
+ fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
+ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+ fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
+ fmt->width = 640;
+ fmt->height = 480;
+ fmt->field = V4L2_FIELD_NONE;
sensor->frame_interval.numerator = 1;
sensor->frame_interval.denominator = ov5640_framerates[OV5640_30_FPS];
sensor->current_fr = OV5640_30_FPS;
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index d28845f7356f..4e3142a7e5a7 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -959,23 +959,6 @@ __ov5645_get_pad_crop(struct ov5645 *ov5645, struct v4l2_subdev_pad_config *cfg,
}
}
-static const struct ov5645_mode_info *
-ov5645_find_nearest_mode(unsigned int width, unsigned int height)
-{
- int i;
-
- for (i = ARRAY_SIZE(ov5645_mode_info_data) - 1; i >= 0; i--) {
- if (ov5645_mode_info_data[i].width <= width &&
- ov5645_mode_info_data[i].height <= height)
- break;
- }
-
- if (i < 0)
- i = 0;
-
- return &ov5645_mode_info_data[i];
-}
-
static int ov5645_set_format(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format)
@@ -989,8 +972,11 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
__crop = __ov5645_get_pad_crop(ov5645, cfg, format->pad,
format->which);
- new_mode = ov5645_find_nearest_mode(format->format.width,
- format->format.height);
+ new_mode = v4l2_find_nearest_size(ov5645_mode_info_data,
+ ARRAY_SIZE(ov5645_mode_info_data),
+ width, height,
+ format->format.width, format->format.height);
+
__crop->width = new_mode->width;
__crop->height = new_mode->height;
@@ -1131,13 +1117,14 @@ static int ov5645_probe(struct i2c_client *client,
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
&ov5645->ep);
+
+ of_node_put(endpoint);
+
if (ret < 0) {
dev_err(dev, "parsing endpoint node failed\n");
return ret;
}
- of_node_put(endpoint);
-
if (ov5645->ep.bus_type != V4L2_MBUS_CSI2) {
dev_err(dev, "invalid bus type, must be CSI2\n");
return -EINVAL;
diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c
index d2db480da1b9..7b7c74d77370 100644
--- a/drivers/media/i2c/ov5670.c
+++ b/drivers/media/i2c/ov5670.c
@@ -1,16 +1,5 @@
-/*
- * Copyright (c) 2017 Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017 Intel Corporation.
#include <linux/acpi.h>
#include <linux/i2c.h>
@@ -2230,7 +2219,9 @@ static int ov5670_set_pad_format(struct v4l2_subdev *sd,
fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
- mode = v4l2_find_nearest_size(supported_modes, width, height,
+ mode = v4l2_find_nearest_size(supported_modes,
+ ARRAY_SIZE(supported_modes),
+ width, height,
fmt->format.width, fmt->format.height);
ov5670_update_pad_format(mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index 226f90886484..af17aaa21f58 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -1081,11 +1081,11 @@ static int mtk_jpeg_clk_init(struct mtk_jpeg_dev *jpeg)
jpeg->clk_jdec = devm_clk_get(jpeg->dev, "jpgdec");
if (IS_ERR(jpeg->clk_jdec))
- return -EINVAL;
+ return PTR_ERR(jpeg->clk_jdec);
jpeg->clk_jdec_smi = devm_clk_get(jpeg->dev, "jpgdec-smi");
if (IS_ERR(jpeg->clk_jdec_smi))
- return -EINVAL;
+ return PTR_ERR(jpeg->clk_jdec_smi);
return 0;
}
diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
index 521d4b36c090..c4a577848dd7 100644
--- a/drivers/media/platform/qcom/venus/firmware.c
+++ b/drivers/media/platform/qcom/venus/firmware.c
@@ -76,7 +76,7 @@ int venus_boot(struct device *dev, const char *fwname)
}
ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys,
- mem_size);
+ mem_size, NULL);
release_firmware(mdt);
diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c
index c9e9576bb08a..49bbd1861d3a 100644
--- a/drivers/media/platform/qcom/venus/vdec.c
+++ b/drivers/media/platform/qcom/venus/vdec.c
@@ -135,20 +135,21 @@ find_format_by_index(struct venus_inst *inst, unsigned int index, u32 type)
return NULL;
for (i = 0; i < size; i++) {
+ bool valid;
+
if (fmt[i].type != type)
continue;
- if (k == index)
+ valid = type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ||
+ venus_helper_check_codec(inst, fmt[i].pixfmt);
+ if (k == index && valid)
break;
- k++;
+ if (valid)
+ k++;
}
if (i == size)
return NULL;
- if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
- !venus_helper_check_codec(inst, fmt[i].pixfmt))
- return NULL;
-
return &fmt[i];
}
diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index e3a10a852cad..6b2ce479584e 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -120,20 +120,21 @@ find_format_by_index(struct venus_inst *inst, unsigned int index, u32 type)
return NULL;
for (i = 0; i < size; i++) {
+ bool valid;
+
if (fmt[i].type != type)
continue;
- if (k == index)
+ valid = type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
+ venus_helper_check_codec(inst, fmt[i].pixfmt);
+ if (k == index && valid)
break;
- k++;
+ if (valid)
+ k++;
}
if (i == size)
return NULL;
- if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
- !venus_helper_check_codec(inst, fmt[i].pixfmt))
- return NULL;
-
return &fmt[i];
}
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index 01c703683657..1599159f2574 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -561,8 +561,9 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
mp->field = vivid_field_cap(dev, mp->field);
if (vivid_is_webcam(dev)) {
const struct v4l2_frmsize_discrete *sz =
- v4l2_find_nearest_size(webcam_sizes, width, height,
- mp->width, mp->height);
+ v4l2_find_nearest_size(webcam_sizes,
+ VIVID_WEBCAM_SIZES, width,
+ height, mp->width, mp->height);
w = sz->width;
h = sz->height;
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index f7f3b4b2c2de..8bd6b2f1af15 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -452,7 +452,7 @@ static void wpf_configure(struct vsp1_entity *entity,
: VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
}
- if (pipe->bru || pipe->num_inputs > 1)
+ if (pipe->bru)
srcrpf |= pipe->bru->type == VSP1_ENTITY_BRU
? VI6_WPF_SRCRPF_VIRACT_MST
: VI6_WPF_SRCRPF_VIRACT2_MST;
diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c
index bc9299059f48..3e14b9e2e763 100644
--- a/drivers/media/tuners/r820t.c
+++ b/drivers/media/tuners/r820t.c
@@ -20,6 +20,8 @@
//
// RF Gain set/get is not implemented.
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/videodev2.h>
#include <linux/mutex.h>
#include <linux/slab.h>
@@ -2371,7 +2373,7 @@ err:
err_no_gate:
mutex_unlock(&r820t_list_mutex);
- tuner_info("%s: failed=%d\n", __func__, rc);
+ pr_info("%s: failed=%d\n", __func__, rc);
r820t_release(fe);
return NULL;
}
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c
index 713029420fcf..67ed66712d05 100644
--- a/drivers/media/usb/cx231xx/cx231xx-dvb.c
+++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c
@@ -276,7 +276,7 @@ static int start_streaming(struct cx231xx_dvb *dvb)
if (dev->USE_ISO) {
dev_dbg(dev->dev, "DVB transfer mode is ISO.\n");
- cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
+ cx231xx_set_alt_setting(dev, INDEX_TS1, 5);
rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
if (rc < 0)
return rc;
diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig
index d214a21acff7..bc9a439745aa 100644
--- a/drivers/media/usb/gspca/Kconfig
+++ b/drivers/media/usb/gspca/Kconfig
@@ -7,7 +7,7 @@ menuconfig USB_GSPCA
Say Y here if you want to enable selecting webcams based
on the GSPCA framework.
- See <file:Documentation/video4linux/gspca.txt> for more info.
+ See <file:Documentation/media/v4l-drivers/gspca-cardlist.rst> for more info.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" to use this driver.
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 5198c9eeb348..4312935f1dfc 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -101,7 +101,7 @@ static int get_v4l2_window32(struct v4l2_window __user *kp,
static int put_v4l2_window32(struct v4l2_window __user *kp,
struct v4l2_window32 __user *up)
{
- struct v4l2_clip __user *kclips = kp->clips;
+ struct v4l2_clip __user *kclips;
struct v4l2_clip32 __user *uclips;
compat_caddr_t p;
u32 clipcount;
@@ -116,6 +116,8 @@ static int put_v4l2_window32(struct v4l2_window __user *kp,
if (!clipcount)
return 0;
+ if (get_user(kclips, &kp->clips))
+ return -EFAULT;
if (get_user(p, &up->clips))
return -EFAULT;
uclips = compat_ptr(p);
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 0301fe426a43..1d0b2208e8fb 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -939,10 +939,14 @@ int __video_register_device(struct video_device *vdev,
#endif
vdev->minor = i + minor_offset;
vdev->num = nr;
- devnode_set(vdev);
/* Should not happen since we thought this minor was free */
- WARN_ON(video_device[vdev->minor] != NULL);
+ if (WARN_ON(video_device[vdev->minor])) {
+ mutex_unlock(&videodev_lock);
+ printk(KERN_ERR "video_device not empty!\n");
+ return -ENFILE;
+ }
+ devnode_set(vdev);
vdev->index = get_index(vdev);
video_device[vdev->minor] = vdev;
mutex_unlock(&videodev_lock);
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c
index 24108bfad889..6193270e7b3d 100644
--- a/drivers/misc/kgdbts.c
+++ b/drivers/misc/kgdbts.c
@@ -400,10 +400,14 @@ static void skip_back_repeat_test(char *arg)
int go_back = simple_strtol(arg, NULL, 10);
repeat_test--;
- if (repeat_test <= 0)
+ if (repeat_test <= 0) {
ts.idx++;
- else
+ } else {
+ if (repeat_test % 100 == 0)
+ v1printk("kgdbts:RUN ... %d remaining\n", repeat_test);
+
ts.idx -= go_back;
+ }
fill_get_buf(ts.tst[ts.idx].get);
}
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 02485e310c81..9e923cd1d80e 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -3080,6 +3080,7 @@ static void __exit mmc_blk_exit(void)
mmc_unregister_driver(&mmc_driver);
unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
+ bus_unregister(&mmc_rpmb_bus_type);
}
module_init(mmc_blk_init);
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index 712e08d9a45e..a0168e9e4fce 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -362,9 +362,9 @@ static void jz4740_mmc_set_irq_enabled(struct jz4740_mmc_host *host,
host->irq_mask &= ~irq;
else
host->irq_mask |= irq;
- spin_unlock_irqrestore(&host->lock, flags);
writew(host->irq_mask, host->base + JZ_REG_MMC_IMASK);
+ spin_unlock_irqrestore(&host->lock, flags);
}
static void jz4740_mmc_clock_enable(struct jz4740_mmc_host *host,
diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c
index e30df9ad8197..308029930304 100644
--- a/drivers/mmc/host/tmio_mmc_core.c
+++ b/drivers/mmc/host/tmio_mmc_core.c
@@ -913,7 +913,7 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
host->check_scc_error(host);
/* If SET_BLOCK_COUNT, continue with main command */
- if (host->mrq) {
+ if (host->mrq && !mrq->cmd->error) {
tmio_process_mrq(host, mrq);
return;
}
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index b1fc28f63882..d0b63bbf46a7 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -244,7 +244,7 @@ static int ubiblock_open(struct block_device *bdev, fmode_t mode)
* in any case.
*/
if (mode & FMODE_WRITE) {
- ret = -EPERM;
+ ret = -EROFS;
goto out_unlock;
}
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index e941395de3ae..753494e042d5 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -854,6 +854,17 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
return -EINVAL;
}
+ /*
+ * Both UBI and UBIFS have been designed for SLC NAND and NOR flashes.
+ * MLC NAND is different and needs special care, otherwise UBI or UBIFS
+ * will die soon and you will lose all your data.
+ */
+ if (mtd->type == MTD_MLCNANDFLASH) {
+ pr_err("ubi: refuse attaching mtd%d - MLC NAND is not supported\n",
+ mtd->index);
+ return -EINVAL;
+ }
+
if (ubi_num == UBI_DEV_NUM_AUTO) {
/* Search for an empty slot in the @ubi_devices array */
for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++)
diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c
index 590d967011bb..98f7d6be8d1f 100644
--- a/drivers/mtd/ubi/fastmap-wl.c
+++ b/drivers/mtd/ubi/fastmap-wl.c
@@ -362,7 +362,6 @@ static void ubi_fastmap_close(struct ubi_device *ubi)
{
int i;
- flush_work(&ubi->fm_work);
return_unused_pool_pebs(ubi, &ubi->fm_pool);
return_unused_pool_pebs(ubi, &ubi->fm_wl_pool);
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 9c2567b0d93e..dfad93fca0a6 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -375,7 +375,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
* because generally mcdi responses are fast. After that, back off
* and poll once a jiffy (approximately)
*/
- spins = TICK_USEC;
+ spins = USER_TICK_USEC;
finish = jiffies + MCDI_RPC_TIMEOUT;
while (1) {
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 6afe896e5cb8..96d26cfae90b 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -253,7 +253,7 @@ static inline void hwsim_clear_chanctx_magic(struct ieee80211_chanctx_conf *c)
static unsigned int hwsim_net_id;
-static struct ida hwsim_netgroup_ida = IDA_INIT;
+static DEFINE_IDA(hwsim_netgroup_ida);
struct hwsim_net {
int netgroup;
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index a65f2e1d9f53..85997184e047 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -20,7 +20,7 @@ if LIBNVDIMM
config BLK_DEV_PMEM
tristate "PMEM: Persistent memory block device support"
default LIBNVDIMM
- select DAX
+ select DAX_DRIVER
select ND_BTT if BTT
select ND_PFN if NVDIMM_PFN
help
@@ -102,4 +102,15 @@ config NVDIMM_DAX
Select Y if unsure
+config OF_PMEM
+ # FIXME: make tristate once OF_NUMA dependency removed
+ bool "Device-tree support for persistent memory regions"
+ depends on OF
+ default LIBNVDIMM
+ help
+ Allows regions of persistent memory to be described in the
+ device-tree.
+
+ Select Y if unsure.
+
endif
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 70d5f3ad9909..e8847045dac0 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_OF_PMEM) += of_pmem.o
nd_pmem-y := pmem.o
diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c
index d58925295aa7..795ad4ff35ca 100644
--- a/drivers/nvdimm/btt_devs.c
+++ b/drivers/nvdimm/btt_devs.c
@@ -26,7 +26,7 @@ static void nd_btt_release(struct device *dev)
struct nd_region *nd_region = to_nd_region(dev->parent);
struct nd_btt *nd_btt = to_nd_btt(dev);
- dev_dbg(dev, "%s\n", __func__);
+ dev_dbg(dev, "trace\n");
nd_detach_ndns(&nd_btt->dev, &nd_btt->ndns);
ida_simple_remove(&nd_region->btt_ida, nd_btt->id);
kfree(nd_btt->uuid);
@@ -74,8 +74,8 @@ static ssize_t sector_size_store(struct device *dev,
nvdimm_bus_lock(dev);
rc = nd_size_select_store(dev, buf, &nd_btt->lbasize,
btt_lbasize_supported);
- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__,
- rc, buf, buf[len - 1] == '\n' ? "" : "\n");
+ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
+ buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
device_unlock(dev);
@@ -101,8 +101,8 @@ static ssize_t uuid_store(struct device *dev,
device_lock(dev);
rc = nd_uuid_store(dev, &nd_btt->uuid, buf, len);
- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__,
- rc, buf, buf[len - 1] == '\n' ? "" : "\n");
+ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
+ buf[len - 1] == '\n' ? "" : "\n");
device_unlock(dev);
return rc ? rc : len;
@@ -131,8 +131,8 @@ static ssize_t namespace_store(struct device *dev,
device_lock(dev);
nvdimm_bus_lock(dev);
rc = nd_namespace_store(dev, &nd_btt->ndns, buf, len);
- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__,
- rc, buf, buf[len - 1] == '\n' ? "" : "\n");
+ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
+ buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
device_unlock(dev);
@@ -206,8 +206,8 @@ static struct device *__nd_btt_create(struct nd_region *nd_region,
dev->groups = nd_btt_attribute_groups;
device_initialize(&nd_btt->dev);
if (ndns && !__nd_attach_ndns(&nd_btt->dev, ndns, &nd_btt->ndns)) {
- dev_dbg(&ndns->dev, "%s failed, already claimed by %s\n",
- __func__, dev_name(ndns->claim));
+ dev_dbg(&ndns->dev, "failed, already claimed by %s\n",
+ dev_name(ndns->claim));
put_device(dev);
return NULL;
}
@@ -346,8 +346,7 @@ int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns)
return -ENOMEM;
btt_sb = devm_kzalloc(dev, sizeof(*btt_sb), GFP_KERNEL);
rc = __nd_btt_probe(to_nd_btt(btt_dev), ndns, btt_sb);
- dev_dbg(dev, "%s: btt: %s\n", __func__,
- rc == 0 ? dev_name(btt_dev) : "<none>");
+ dev_dbg(dev, "btt: %s\n", rc == 0 ? dev_name(btt_dev) : "<none>");
if (rc < 0) {
struct nd_btt *nd_btt = to_nd_btt(btt_dev);
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 78eabc3a1ab1..a64023690cad 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -358,6 +358,7 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
nvdimm_bus->dev.release = nvdimm_bus_release;
nvdimm_bus->dev.groups = nd_desc->attr_groups;
nvdimm_bus->dev.bus = &nvdimm_bus_type;
+ nvdimm_bus->dev.of_node = nd_desc->of_node;
dev_set_name(&nvdimm_bus->dev, "ndbus%d", nvdimm_bus->id);
rc = device_register(&nvdimm_bus->dev);
if (rc) {
@@ -984,8 +985,8 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
if (cmd == ND_CMD_CALL) {
func = pkg.nd_command;
- dev_dbg(dev, "%s:%s, idx: %llu, in: %u, out: %u, len %llu\n",
- __func__, dimm_name, pkg.nd_command,
+ dev_dbg(dev, "%s, idx: %llu, in: %u, out: %u, len %llu\n",
+ dimm_name, pkg.nd_command,
in_len, out_len, buf_len);
}
@@ -996,8 +997,8 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
u32 copy;
if (out_size == UINT_MAX) {
- dev_dbg(dev, "%s:%s unknown output size cmd: %s field: %d\n",
- __func__, dimm_name, cmd_name, i);
+ dev_dbg(dev, "%s unknown output size cmd: %s field: %d\n",
+ dimm_name, cmd_name, i);
return -EFAULT;
}
if (out_len < sizeof(out_env))
@@ -1012,9 +1013,8 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
buf_len = (u64) out_len + (u64) in_len;
if (buf_len > ND_IOCTL_MAX_BUFLEN) {
- dev_dbg(dev, "%s:%s cmd: %s buf_len: %llu > %d\n", __func__,
- dimm_name, cmd_name, buf_len,
- ND_IOCTL_MAX_BUFLEN);
+ dev_dbg(dev, "%s cmd: %s buf_len: %llu > %d\n", dimm_name,
+ cmd_name, buf_len, ND_IOCTL_MAX_BUFLEN);
return -EINVAL;
}
diff --git a/drivers/nvdimm/claim.c b/drivers/nvdimm/claim.c
index b2fc29b8279b..30852270484f 100644
--- a/drivers/nvdimm/claim.c
+++ b/drivers/nvdimm/claim.c
@@ -148,7 +148,7 @@ ssize_t nd_namespace_store(struct device *dev,
char *name;
if (dev->driver) {
- dev_dbg(dev, "%s: -EBUSY\n", __func__);
+ dev_dbg(dev, "namespace already active\n");
return -EBUSY;
}
diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c
index 1dc527660637..acce050856a8 100644
--- a/drivers/nvdimm/core.c
+++ b/drivers/nvdimm/core.c
@@ -134,7 +134,7 @@ static void nvdimm_map_release(struct kref *kref)
nvdimm_map = container_of(kref, struct nvdimm_map, kref);
nvdimm_bus = nvdimm_map->nvdimm_bus;
- dev_dbg(&nvdimm_bus->dev, "%s: %pa\n", __func__, &nvdimm_map->offset);
+ dev_dbg(&nvdimm_bus->dev, "%pa\n", &nvdimm_map->offset);
list_del(&nvdimm_map->list);
if (nvdimm_map->flags)
memunmap(nvdimm_map->mem);
@@ -230,8 +230,8 @@ static int nd_uuid_parse(struct device *dev, u8 *uuid_out, const char *buf,
for (i = 0; i < 16; i++) {
if (!isxdigit(str[0]) || !isxdigit(str[1])) {
- dev_dbg(dev, "%s: pos: %d buf[%zd]: %c buf[%zd]: %c\n",
- __func__, i, str - buf, str[0],
+ dev_dbg(dev, "pos: %d buf[%zd]: %c buf[%zd]: %c\n",
+ i, str - buf, str[0],
str + 1 - buf, str[1]);
return -EINVAL;
}
diff --git a/drivers/nvdimm/dax_devs.c b/drivers/nvdimm/dax_devs.c
index 1bf2bd318371..0453f49dc708 100644
--- a/drivers/nvdimm/dax_devs.c
+++ b/drivers/nvdimm/dax_devs.c
@@ -24,7 +24,7 @@ static void nd_dax_release(struct device *dev)
struct nd_dax *nd_dax = to_nd_dax(dev);
struct nd_pfn *nd_pfn = &nd_dax->nd_pfn;
- dev_dbg(dev, "%s\n", __func__);
+ dev_dbg(dev, "trace\n");
nd_detach_ndns(dev, &nd_pfn->ndns);
ida_simple_remove(&nd_region->dax_ida, nd_pfn->id);
kfree(nd_pfn->uuid);
@@ -129,8 +129,7 @@ int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns)
pfn_sb = devm_kzalloc(dev, sizeof(*pfn_sb), GFP_KERNEL);
nd_pfn->pfn_sb = pfn_sb;
rc = nd_pfn_validate(nd_pfn, DAX_SIG);
- dev_dbg(dev, "%s: dax: %s\n", __func__,
- rc == 0 ? dev_name(dax_dev) : "<none>");
+ dev_dbg(dev, "dax: %s\n", rc == 0 ? dev_name(dax_dev) : "<none>");
if (rc < 0) {
nd_detach_ndns(dax_dev, &nd_pfn->ndns);
put_device(dax_dev);
diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c
index f8913b8124b6..233907889f96 100644
--- a/drivers/nvdimm/dimm.c
+++ b/drivers/nvdimm/dimm.c
@@ -67,9 +67,11 @@ static int nvdimm_probe(struct device *dev)
ndd->ns_next = nd_label_next_nsindex(ndd->ns_current);
nd_label_copy(ndd, to_next_namespace_index(ndd),
to_current_namespace_index(ndd));
- rc = nd_label_reserve_dpa(ndd);
- if (ndd->ns_current >= 0)
- nvdimm_set_aliasing(dev);
+ if (ndd->ns_current >= 0) {
+ rc = nd_label_reserve_dpa(ndd);
+ if (rc == 0)
+ nvdimm_set_aliasing(dev);
+ }
nvdimm_clear_locked(dev);
nvdimm_bus_unlock(dev);
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 097794d9f786..e00d45522b80 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -131,7 +131,7 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
}
memcpy(ndd->data + offset, cmd->out_buf, cmd->in_length);
}
- dev_dbg(ndd->dev, "%s: len: %zu rc: %d\n", __func__, offset, rc);
+ dev_dbg(ndd->dev, "len: %zu rc: %d\n", offset, rc);
kfree(cmd);
return rc;
@@ -266,8 +266,7 @@ void nvdimm_drvdata_release(struct kref *kref)
struct device *dev = ndd->dev;
struct resource *res, *_r;
- dev_dbg(dev, "%s\n", __func__);
-
+ dev_dbg(dev, "trace\n");
nvdimm_bus_lock(dev);
for_each_dpa_resource_safe(ndd, res, _r)
nvdimm_free_dpa(ndd, res);
@@ -660,7 +659,7 @@ int nvdimm_bus_check_dimm_count(struct nvdimm_bus *nvdimm_bus, int dimm_count)
nd_synchronize();
device_for_each_child(&nvdimm_bus->dev, &count, count_dimms);
- dev_dbg(&nvdimm_bus->dev, "%s: count: %d\n", __func__, count);
+ dev_dbg(&nvdimm_bus->dev, "count: %d\n", count);
if (count != dimm_count)
return -ENXIO;
return 0;
diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index de66c02f6140..1d28cd656536 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -45,9 +45,27 @@ unsigned sizeof_namespace_label(struct nvdimm_drvdata *ndd)
return ndd->nslabel_size;
}
+static size_t __sizeof_namespace_index(u32 nslot)
+{
+ return ALIGN(sizeof(struct nd_namespace_index) + DIV_ROUND_UP(nslot, 8),
+ NSINDEX_ALIGN);
+}
+
+static int __nvdimm_num_label_slots(struct nvdimm_drvdata *ndd,
+ size_t index_size)
+{
+ return (ndd->nsarea.config_size - index_size * 2) /
+ sizeof_namespace_label(ndd);
+}
+
int nvdimm_num_label_slots(struct nvdimm_drvdata *ndd)
{
- return ndd->nsarea.config_size / (sizeof_namespace_label(ndd) + 1);
+ u32 tmp_nslot, n;
+
+ tmp_nslot = ndd->nsarea.config_size / sizeof_namespace_label(ndd);
+ n = __sizeof_namespace_index(tmp_nslot) / NSINDEX_ALIGN;
+
+ return __nvdimm_num_label_slots(ndd, NSINDEX_ALIGN * n);
}
size_t sizeof_namespace_index(struct nvdimm_drvdata *ndd)
@@ -55,18 +73,14 @@ size_t sizeof_namespace_index(struct nvdimm_drvdata *ndd)
u32 nslot, space, size;
/*
- * The minimum index space is 512 bytes, with that amount of
- * index we can describe ~1400 labels which is less than a byte
- * of overhead per label. Round up to a byte of overhead per
- * label and determine the size of the index region. Yes, this
- * starts to waste space at larger config_sizes, but it's
- * unlikely we'll ever see anything but 128K.
+ * Per UEFI 2.7, the minimum size of the Label Storage Area is large
+ * enough to hold 2 index blocks and 2 labels. The minimum index
+ * block size is 256 bytes, and the minimum label size is 256 bytes.
*/
nslot = nvdimm_num_label_slots(ndd);
space = ndd->nsarea.config_size - nslot * sizeof_namespace_label(ndd);
- size = ALIGN(sizeof(struct nd_namespace_index) + DIV_ROUND_UP(nslot, 8),
- NSINDEX_ALIGN) * 2;
- if (size <= space)
+ size = __sizeof_namespace_index(nslot) * 2;
+ if (size <= space && nslot >= 2)
return size / 2;
dev_err(ndd->dev, "label area (%d) too small to host (%d byte) labels\n",
@@ -121,8 +135,7 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd)
memcpy(sig, nsindex[i]->sig, NSINDEX_SIG_LEN);
if (memcmp(sig, NSINDEX_SIGNATURE, NSINDEX_SIG_LEN) != 0) {
- dev_dbg(dev, "%s: nsindex%d signature invalid\n",
- __func__, i);
+ dev_dbg(dev, "nsindex%d signature invalid\n", i);
continue;
}
@@ -135,8 +148,8 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd)
labelsize = 128;
if (labelsize != sizeof_namespace_label(ndd)) {
- dev_dbg(dev, "%s: nsindex%d labelsize %d invalid\n",
- __func__, i, nsindex[i]->labelsize);
+ dev_dbg(dev, "nsindex%d labelsize %d invalid\n",
+ i, nsindex[i]->labelsize);
continue;
}
@@ -145,30 +158,28 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd)
sum = nd_fletcher64(nsindex[i], sizeof_namespace_index(ndd), 1);
nsindex[i]->checksum = __cpu_to_le64(sum_save);
if (sum != sum_save) {
- dev_dbg(dev, "%s: nsindex%d checksum invalid\n",
- __func__, i);
+ dev_dbg(dev, "nsindex%d checksum invalid\n", i);
continue;
}
seq = __le32_to_cpu(nsindex[i]->seq);
if ((seq & NSINDEX_SEQ_MASK) == 0) {
- dev_dbg(dev, "%s: nsindex%d sequence: %#x invalid\n",
- __func__, i, seq);
+ dev_dbg(dev, "nsindex%d sequence: %#x invalid\n", i, seq);
continue;
}
/* sanity check the index against expected values */
if (__le64_to_cpu(nsindex[i]->myoff)
!= i * sizeof_namespace_index(ndd)) {
- dev_dbg(dev, "%s: nsindex%d myoff: %#llx invalid\n",
- __func__, i, (unsigned long long)
+ dev_dbg(dev, "nsindex%d myoff: %#llx invalid\n",
+ i, (unsigned long long)
__le64_to_cpu(nsindex[i]->myoff));
continue;
}
if (__le64_to_cpu(nsindex[i]->otheroff)
!= (!i) * sizeof_namespace_index(ndd)) {
- dev_dbg(dev, "%s: nsindex%d otheroff: %#llx invalid\n",
- __func__, i, (unsigned long long)
+ dev_dbg(dev, "nsindex%d otheroff: %#llx invalid\n",
+ i, (unsigned long long)
__le64_to_cpu(nsindex[i]->otheroff));
continue;
}
@@ -176,8 +187,7 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd)
size = __le64_to_cpu(nsindex[i]->mysize);
if (size > sizeof_namespace_index(ndd)
|| size < sizeof(struct nd_namespace_index)) {
- dev_dbg(dev, "%s: nsindex%d mysize: %#llx invalid\n",
- __func__, i, size);
+ dev_dbg(dev, "nsindex%d mysize: %#llx invalid\n", i, size);
continue;
}
@@ -185,9 +195,8 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd)
if (nslot * sizeof_namespace_label(ndd)
+ 2 * sizeof_namespace_index(ndd)
> ndd->nsarea.config_size) {
- dev_dbg(dev, "%s: nsindex%d nslot: %u invalid, config_size: %#x\n",
- __func__, i, nslot,
- ndd->nsarea.config_size);
+ dev_dbg(dev, "nsindex%d nslot: %u invalid, config_size: %#x\n",
+ i, nslot, ndd->nsarea.config_size);
continue;
}
valid[i] = true;
@@ -356,8 +365,8 @@ static bool slot_valid(struct nvdimm_drvdata *ndd,
sum = nd_fletcher64(nd_label, sizeof_namespace_label(ndd), 1);
nd_label->checksum = __cpu_to_le64(sum_save);
if (sum != sum_save) {
- dev_dbg(ndd->dev, "%s fail checksum. slot: %d expect: %#llx\n",
- __func__, slot, sum);
+ dev_dbg(ndd->dev, "fail checksum. slot: %d expect: %#llx\n",
+ slot, sum);
return false;
}
}
@@ -422,8 +431,8 @@ int nd_label_active_count(struct nvdimm_drvdata *ndd)
u64 dpa = __le64_to_cpu(nd_label->dpa);
dev_dbg(ndd->dev,
- "%s: slot%d invalid slot: %d dpa: %llx size: %llx\n",
- __func__, slot, label_slot, dpa, size);
+ "slot%d invalid slot: %d dpa: %llx size: %llx\n",
+ slot, label_slot, dpa, size);
continue;
}
count++;
@@ -650,7 +659,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
slot = nd_label_alloc_slot(ndd);
if (slot == UINT_MAX)
return -ENXIO;
- dev_dbg(ndd->dev, "%s: allocated: %d\n", __func__, slot);
+ dev_dbg(ndd->dev, "allocated: %d\n", slot);
nd_label = to_label(ndd, slot);
memset(nd_label, 0, sizeof_namespace_label(ndd));
@@ -678,7 +687,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
sum = nd_fletcher64(nd_label, sizeof_namespace_label(ndd), 1);
nd_label->checksum = __cpu_to_le64(sum);
}
- nd_dbg_dpa(nd_region, ndd, res, "%s\n", __func__);
+ nd_dbg_dpa(nd_region, ndd, res, "\n");
/* update label */
offset = nd_label_offset(ndd, nd_label);
@@ -700,7 +709,7 @@ static int __pmem_label_update(struct nd_region *nd_region,
break;
}
if (victim) {
- dev_dbg(ndd->dev, "%s: free: %d\n", __func__, slot);
+ dev_dbg(ndd->dev, "free: %d\n", slot);
slot = to_slot(ndd, victim->label);
nd_label_free_slot(ndd, slot);
victim->label = NULL;
@@ -868,7 +877,7 @@ static int __blk_label_update(struct nd_region *nd_region,
slot = nd_label_alloc_slot(ndd);
if (slot == UINT_MAX)
goto abort;
- dev_dbg(ndd->dev, "%s: allocated: %d\n", __func__, slot);
+ dev_dbg(ndd->dev, "allocated: %d\n", slot);
nd_label = to_label(ndd, slot);
memset(nd_label, 0, sizeof_namespace_label(ndd));
@@ -928,7 +937,7 @@ static int __blk_label_update(struct nd_region *nd_region,
/* free up now unused slots in the new index */
for_each_set_bit(slot, victim_map, victim_map ? nslot : 0) {
- dev_dbg(ndd->dev, "%s: free: %d\n", __func__, slot);
+ dev_dbg(ndd->dev, "free: %d\n", slot);
nd_label_free_slot(ndd, slot);
}
@@ -1092,7 +1101,7 @@ static int del_labels(struct nd_mapping *nd_mapping, u8 *uuid)
active--;
slot = to_slot(ndd, nd_label);
nd_label_free_slot(ndd, slot);
- dev_dbg(ndd->dev, "%s: free: %d\n", __func__, slot);
+ dev_dbg(ndd->dev, "free: %d\n", slot);
list_move_tail(&label_ent->list, &list);
label_ent->label = NULL;
}
@@ -1100,7 +1109,7 @@ static int del_labels(struct nd_mapping *nd_mapping, u8 *uuid)
if (active == 0) {
nd_mapping_free_labels(nd_mapping);
- dev_dbg(ndd->dev, "%s: no more active labels\n", __func__);
+ dev_dbg(ndd->dev, "no more active labels\n");
}
mutex_unlock(&nd_mapping->lock);
diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
index 1ebf4d3d01ba..18bbe183b3a9 100644
--- a/drivers/nvdimm/label.h
+++ b/drivers/nvdimm/label.h
@@ -33,7 +33,7 @@ enum {
BTTINFO_UUID_LEN = 16,
BTTINFO_FLAG_ERROR = 0x1, /* error state (read-only) */
BTTINFO_MAJOR_VERSION = 1,
- ND_LABEL_MIN_SIZE = 512 * 129, /* see sizeof_namespace_index() */
+ ND_LABEL_MIN_SIZE = 256 * 4, /* see sizeof_namespace_index() */
ND_LABEL_ID_SIZE = 50,
ND_NSINDEX_INIT = 0x1,
};
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 658ada497be0..28afdd668905 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -421,7 +421,7 @@ static ssize_t alt_name_store(struct device *dev,
rc = __alt_name_store(dev, buf, len);
if (rc >= 0)
rc = nd_namespace_label_update(nd_region, dev);
- dev_dbg(dev, "%s: %s(%zd)\n", __func__, rc < 0 ? "fail " : "", rc);
+ dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc);
nvdimm_bus_unlock(dev);
device_unlock(dev);
@@ -1007,7 +1007,7 @@ static ssize_t __size_store(struct device *dev, unsigned long long val)
if (uuid_not_set(uuid, dev, __func__))
return -ENXIO;
if (nd_region->ndr_mappings == 0) {
- dev_dbg(dev, "%s: not associated with dimm(s)\n", __func__);
+ dev_dbg(dev, "not associated with dimm(s)\n");
return -ENXIO;
}
@@ -1105,8 +1105,7 @@ static ssize_t size_store(struct device *dev,
*uuid = NULL;
}
- dev_dbg(dev, "%s: %llx %s (%d)\n", __func__, val, rc < 0
- ? "fail" : "success", rc);
+ dev_dbg(dev, "%llx %s (%d)\n", val, rc < 0 ? "fail" : "success", rc);
nvdimm_bus_unlock(dev);
device_unlock(dev);
@@ -1270,8 +1269,8 @@ static ssize_t uuid_store(struct device *dev,
rc = nd_namespace_label_update(nd_region, dev);
else
kfree(uuid);
- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__,
- rc, buf, buf[len - 1] == '\n' ? "" : "\n");
+ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
+ buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
device_unlock(dev);
@@ -1355,9 +1354,8 @@ static ssize_t sector_size_store(struct device *dev,
rc = nd_size_select_store(dev, buf, lbasize, supported);
if (rc >= 0)
rc = nd_namespace_label_update(nd_region, dev);
- dev_dbg(dev, "%s: result: %zd %s: %s%s", __func__,
- rc, rc < 0 ? "tried" : "wrote", buf,
- buf[len - 1] == '\n' ? "" : "\n");
+ dev_dbg(dev, "result: %zd %s: %s%s", rc, rc < 0 ? "tried" : "wrote",
+ buf, buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
device_unlock(dev);
@@ -1519,7 +1517,7 @@ static ssize_t holder_class_store(struct device *dev,
rc = __holder_class_store(dev, buf);
if (rc >= 0)
rc = nd_namespace_label_update(nd_region, dev);
- dev_dbg(dev, "%s: %s(%zd)\n", __func__, rc < 0 ? "fail " : "", rc);
+ dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc);
nvdimm_bus_unlock(dev);
device_unlock(dev);
@@ -1717,8 +1715,7 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev)
if (uuid_not_set(nsblk->uuid, &ndns->dev, __func__))
return ERR_PTR(-ENODEV);
if (!nsblk->lbasize) {
- dev_dbg(&ndns->dev, "%s: sector size not set\n",
- __func__);
+ dev_dbg(&ndns->dev, "sector size not set\n");
return ERR_PTR(-ENODEV);
}
if (!nd_namespace_blk_validate(nsblk))
@@ -1798,9 +1795,7 @@ static bool has_uuid_at_pos(struct nd_region *nd_region, u8 *uuid,
}
if (found_uuid) {
- dev_dbg(ndd->dev,
- "%s duplicate entry for uuid\n",
- __func__);
+ dev_dbg(ndd->dev, "duplicate entry for uuid\n");
return false;
}
found_uuid = true;
@@ -1926,7 +1921,7 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
}
if (i < nd_region->ndr_mappings) {
- struct nvdimm_drvdata *ndd = to_ndd(&nd_region->mapping[i]);
+ struct nvdimm *nvdimm = nd_region->mapping[i].nvdimm;
/*
* Give up if we don't find an instance of a uuid at each
@@ -1934,7 +1929,7 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
* find a dimm with two instances of the same uuid.
*/
dev_err(&nd_region->dev, "%s missing label for %pUb\n",
- dev_name(ndd->dev), nd_label->uuid);
+ nvdimm_name(nvdimm), nd_label->uuid);
rc = -EINVAL;
goto err;
}
@@ -1994,14 +1989,13 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
namespace_pmem_release(dev);
switch (rc) {
case -EINVAL:
- dev_dbg(&nd_region->dev, "%s: invalid label(s)\n", __func__);
+ dev_dbg(&nd_region->dev, "invalid label(s)\n");
break;
case -ENODEV:
- dev_dbg(&nd_region->dev, "%s: label not found\n", __func__);
+ dev_dbg(&nd_region->dev, "label not found\n");
break;
default:
- dev_dbg(&nd_region->dev, "%s: unexpected err: %d\n",
- __func__, rc);
+ dev_dbg(&nd_region->dev, "unexpected err: %d\n", rc);
break;
}
return ERR_PTR(rc);
@@ -2334,8 +2328,8 @@ static struct device **scan_labels(struct nd_region *nd_region)
}
- dev_dbg(&nd_region->dev, "%s: discovered %d %s namespace%s\n",
- __func__, count, is_nd_blk(&nd_region->dev)
+ dev_dbg(&nd_region->dev, "discovered %d %s namespace%s\n",
+ count, is_nd_blk(&nd_region->dev)
? "blk" : "pmem", count == 1 ? "" : "s");
if (count == 0) {
@@ -2467,7 +2461,7 @@ static int init_active_labels(struct nd_region *nd_region)
get_ndd(ndd);
count = nd_label_active_count(ndd);
- dev_dbg(ndd->dev, "%s: %d\n", __func__, count);
+ dev_dbg(ndd->dev, "count: %d\n", count);
if (!count)
continue;
for (j = 0; j < count; j++) {
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 184e070d50a2..32e0364b48b9 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -340,7 +340,6 @@ static inline struct device *nd_dax_create(struct nd_region *nd_region)
}
#endif
-struct nd_region *to_nd_region(struct device *dev);
int nd_region_to_nstype(struct nd_region *nd_region);
int nd_region_register_namespaces(struct nd_region *nd_region, int *err);
u64 nd_region_interleave_set_cookie(struct nd_region *nd_region,
diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
new file mode 100644
index 000000000000..85013bad35de
--- /dev/null
+++ b/drivers/nvdimm/of_pmem.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#define pr_fmt(fmt) "of_pmem: " fmt
+
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/libnvdimm.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+static const struct attribute_group *region_attr_groups[] = {
+ &nd_region_attribute_group,
+ &nd_device_attribute_group,
+ NULL,
+};
+
+static const struct attribute_group *bus_attr_groups[] = {
+ &nvdimm_bus_attribute_group,
+ NULL,
+};
+
+struct of_pmem_private {
+ struct nvdimm_bus_descriptor bus_desc;
+ struct nvdimm_bus *bus;
+};
+
+static int of_pmem_region_probe(struct platform_device *pdev)
+{
+ struct of_pmem_private *priv;
+ struct device_node *np;
+ struct nvdimm_bus *bus;
+ bool is_volatile;
+ int i;
+
+ np = dev_of_node(&pdev->dev);
+ if (!np)
+ return -ENXIO;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->bus_desc.attr_groups = bus_attr_groups;
+ priv->bus_desc.provider_name = "of_pmem";
+ priv->bus_desc.module = THIS_MODULE;
+ priv->bus_desc.of_node = np;
+
+ priv->bus = bus = nvdimm_bus_register(&pdev->dev, &priv->bus_desc);
+ if (!bus) {
+ kfree(priv);
+ return -ENODEV;
+ }
+ platform_set_drvdata(pdev, priv);
+
+ is_volatile = !!of_find_property(np, "volatile", NULL);
+ dev_dbg(&pdev->dev, "Registering %s regions from %pOF\n",
+ is_volatile ? "volatile" : "non-volatile", np);
+
+ for (i = 0; i < pdev->num_resources; i++) {
+ struct nd_region_desc ndr_desc;
+ struct nd_region *region;
+
+ /*
+ * NB: libnvdimm copies the data from ndr_desc into it's own
+ * structures so passing a stack pointer is fine.
+ */
+ memset(&ndr_desc, 0, sizeof(ndr_desc));
+ ndr_desc.attr_groups = region_attr_groups;
+ ndr_desc.numa_node = of_node_to_nid(np);
+ ndr_desc.res = &pdev->resource[i];
+ ndr_desc.of_node = np;
+ set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
+
+ if (is_volatile)
+ region = nvdimm_volatile_region_create(bus, &ndr_desc);
+ else
+ region = nvdimm_pmem_region_create(bus, &ndr_desc);
+
+ if (!region)
+ dev_warn(&pdev->dev, "Unable to register region %pR from %pOF\n",
+ ndr_desc.res, np);
+ else
+ dev_dbg(&pdev->dev, "Registered region %pR from %pOF\n",
+ ndr_desc.res, np);
+ }
+
+ return 0;
+}
+
+static int of_pmem_region_remove(struct platform_device *pdev)
+{
+ struct of_pmem_private *priv = platform_get_drvdata(pdev);
+
+ nvdimm_bus_unregister(priv->bus);
+ kfree(priv);
+
+ return 0;
+}
+
+static const struct of_device_id of_pmem_region_match[] = {
+ { .compatible = "pmem-region" },
+ { },
+};
+
+static struct platform_driver of_pmem_region_driver = {
+ .probe = of_pmem_region_probe,
+ .remove = of_pmem_region_remove,
+ .driver = {
+ .name = "of_pmem",
+ .owner = THIS_MODULE,
+ .of_match_table = of_pmem_region_match,
+ },
+};
+
+module_platform_driver(of_pmem_region_driver);
+MODULE_DEVICE_TABLE(of, of_pmem_region_match);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("IBM Corporation");
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index 2f4d18752c97..30b08791597d 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -27,7 +27,7 @@ static void nd_pfn_release(struct device *dev)
struct nd_region *nd_region = to_nd_region(dev->parent);
struct nd_pfn *nd_pfn = to_nd_pfn(dev);
- dev_dbg(dev, "%s\n", __func__);
+ dev_dbg(dev, "trace\n");
nd_detach_ndns(&nd_pfn->dev, &nd_pfn->ndns);
ida_simple_remove(&nd_region->pfn_ida, nd_pfn->id);
kfree(nd_pfn->uuid);
@@ -94,8 +94,8 @@ static ssize_t mode_store(struct device *dev,
else
rc = -EINVAL;
}
- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__,
- rc, buf, buf[len - 1] == '\n' ? "" : "\n");
+ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
+ buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
device_unlock(dev);
@@ -144,8 +144,8 @@ static ssize_t align_store(struct device *dev,
nvdimm_bus_lock(dev);
rc = nd_size_select_store(dev, buf, &nd_pfn->align,
nd_pfn_supported_alignments());
- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__,
- rc, buf, buf[len - 1] == '\n' ? "" : "\n");
+ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
+ buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
device_unlock(dev);
@@ -171,8 +171,8 @@ static ssize_t uuid_store(struct device *dev,
device_lock(dev);
rc = nd_uuid_store(dev, &nd_pfn->uuid, buf, len);
- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__,
- rc, buf, buf[len - 1] == '\n' ? "" : "\n");
+ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
+ buf[len - 1] == '\n' ? "" : "\n");
device_unlock(dev);
return rc ? rc : len;
@@ -201,8 +201,8 @@ static ssize_t namespace_store(struct device *dev,
device_lock(dev);
nvdimm_bus_lock(dev);
rc = nd_namespace_store(dev, &nd_pfn->ndns, buf, len);
- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__,
- rc, buf, buf[len - 1] == '\n' ? "" : "\n");
+ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
+ buf[len - 1] == '\n' ? "" : "\n");
nvdimm_bus_unlock(dev);
device_unlock(dev);
@@ -314,8 +314,8 @@ struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
dev = &nd_pfn->dev;
device_initialize(&nd_pfn->dev);
if (ndns && !__nd_attach_ndns(&nd_pfn->dev, ndns, &nd_pfn->ndns)) {
- dev_dbg(&ndns->dev, "%s failed, already claimed by %s\n",
- __func__, dev_name(ndns->claim));
+ dev_dbg(&ndns->dev, "failed, already claimed by %s\n",
+ dev_name(ndns->claim));
put_device(dev);
return NULL;
}
@@ -510,8 +510,7 @@ int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns)
nd_pfn = to_nd_pfn(pfn_dev);
nd_pfn->pfn_sb = pfn_sb;
rc = nd_pfn_validate(nd_pfn, PFN_SIG);
- dev_dbg(dev, "%s: pfn: %s\n", __func__,
- rc == 0 ? dev_name(pfn_dev) : "<none>");
+ dev_dbg(dev, "pfn: %s\n", rc == 0 ? dev_name(pfn_dev) : "<none>");
if (rc < 0) {
nd_detach_ndns(pfn_dev, &nd_pfn->ndns);
put_device(pfn_dev);
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 5a96d30c294a..9d714926ecf5 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -66,7 +66,7 @@ static blk_status_t pmem_clear_poison(struct pmem_device *pmem,
rc = BLK_STS_IOERR;
if (cleared > 0 && cleared / 512) {
cleared /= 512;
- dev_dbg(dev, "%s: %#llx clear %ld sector%s\n", __func__,
+ dev_dbg(dev, "%#llx clear %ld sector%s\n",
(unsigned long long) sector, cleared,
cleared > 1 ? "s" : "");
badblocks_clear(&pmem->bb, sector, cleared);
@@ -547,17 +547,7 @@ static struct nd_device_driver nd_pmem_driver = {
.type = ND_DRIVER_NAMESPACE_IO | ND_DRIVER_NAMESPACE_PMEM,
};
-static int __init pmem_init(void)
-{
- return nd_driver_register(&nd_pmem_driver);
-}
-module_init(pmem_init);
-
-static void pmem_exit(void)
-{
- driver_unregister(&nd_pmem_driver.drv);
-}
-module_exit(pmem_exit);
+module_nd_driver(nd_pmem_driver);
MODULE_AUTHOR("Ross Zwisler <ross.zwisler@linux.intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvdimm/region.c b/drivers/nvdimm/region.c
index 034f0a07d627..b9ca0033cc99 100644
--- a/drivers/nvdimm/region.c
+++ b/drivers/nvdimm/region.c
@@ -27,10 +27,10 @@ static int nd_region_probe(struct device *dev)
if (nd_region->num_lanes > num_online_cpus()
&& nd_region->num_lanes < num_possible_cpus()
&& !test_and_set_bit(0, &once)) {
- dev_info(dev, "online cpus (%d) < concurrent i/o lanes (%d) < possible cpus (%d)\n",
+ dev_dbg(dev, "online cpus (%d) < concurrent i/o lanes (%d) < possible cpus (%d)\n",
num_online_cpus(), nd_region->num_lanes,
num_possible_cpus());
- dev_info(dev, "setting nr_cpus=%d may yield better libnvdimm device performance\n",
+ dev_dbg(dev, "setting nr_cpus=%d may yield better libnvdimm device performance\n",
nd_region->num_lanes);
}
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 1593e1806b16..a612be6f019d 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -182,6 +182,14 @@ struct nd_region *to_nd_region(struct device *dev)
}
EXPORT_SYMBOL_GPL(to_nd_region);
+struct device *nd_region_dev(struct nd_region *nd_region)
+{
+ if (!nd_region)
+ return NULL;
+ return &nd_region->dev;
+}
+EXPORT_SYMBOL_GPL(nd_region_dev);
+
struct nd_blk_region *to_nd_blk_region(struct device *dev)
{
struct nd_region *nd_region = to_nd_region(dev);
@@ -1014,6 +1022,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
dev->parent = &nvdimm_bus->dev;
dev->type = dev_type;
dev->groups = ndr_desc->attr_groups;
+ dev->of_node = ndr_desc->of_node;
nd_region->ndr_size = resource_size(ndr_desc->res);
nd_region->ndr_start = ndr_desc->res->start;
nd_device_register(dev);
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 02c5984ab09b..6bb37c18292a 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -295,7 +295,7 @@ static void __init of_unittest_printf(void)
return;
}
- num_to_str(phandle_str, sizeof(phandle_str), np->phandle);
+ num_to_str(phandle_str, sizeof(phandle_str), np->phandle, 0);
of_unittest_printf_one(np, "%pOF", full_name);
of_unittest_printf_one(np, "%pOFf", full_name);
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
index 313cf8ad77bf..ea9e7f4479ca 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -93,9 +93,11 @@ struct mlxreg_hotplug_priv_data {
bool after_probe;
};
-static int mlxreg_hotplug_device_create(struct device *dev,
+static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
struct mlxreg_core_data *data)
{
+ struct mlxreg_core_hotplug_platform_data *pdata;
+
/*
* Return if adapter number is negative. It could be in case hotplug
* event is not associated with hotplug device.
@@ -103,19 +105,21 @@ static int mlxreg_hotplug_device_create(struct device *dev,
if (data->hpdev.nr < 0)
return 0;
- data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);
+ pdata = dev_get_platdata(&priv->pdev->dev);
+ data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr +
+ pdata->shift_nr);
if (!data->hpdev.adapter) {
- dev_err(dev, "Failed to get adapter for bus %d\n",
- data->hpdev.nr);
+ dev_err(priv->dev, "Failed to get adapter for bus %d\n",
+ data->hpdev.nr + pdata->shift_nr);
return -EFAULT;
}
data->hpdev.client = i2c_new_device(data->hpdev.adapter,
data->hpdev.brdinfo);
if (!data->hpdev.client) {
- dev_err(dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
- data->hpdev.brdinfo->type, data->hpdev.nr,
- data->hpdev.brdinfo->addr);
+ dev_err(priv->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
+ data->hpdev.brdinfo->type, data->hpdev.nr +
+ pdata->shift_nr, data->hpdev.brdinfo->addr);
i2c_put_adapter(data->hpdev.adapter);
data->hpdev.adapter = NULL;
@@ -270,10 +274,10 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
if (item->inversed)
mlxreg_hotplug_device_destroy(data);
else
- mlxreg_hotplug_device_create(priv->dev, data);
+ mlxreg_hotplug_device_create(priv, data);
} else {
if (item->inversed)
- mlxreg_hotplug_device_create(priv->dev, data);
+ mlxreg_hotplug_device_create(priv, data);
else
mlxreg_hotplug_device_destroy(data);
}
@@ -319,7 +323,7 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
if (regval == MLXREG_HOTPLUG_HEALTH_MASK) {
if ((data->health_cntr++ == MLXREG_HOTPLUG_RST_CNTR) ||
!priv->after_probe) {
- mlxreg_hotplug_device_create(priv->dev, data);
+ mlxreg_hotplug_device_create(priv, data);
data->attached = true;
}
} else {
@@ -550,6 +554,7 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
{
struct mlxreg_core_hotplug_platform_data *pdata;
struct mlxreg_hotplug_priv_data *priv;
+ struct i2c_adapter *deferred_adap;
int err;
pdata = dev_get_platdata(&pdev->dev);
@@ -558,6 +563,12 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
return -EINVAL;
}
+ /* Defer probing if the necessary adapter is not configured yet. */
+ deferred_adap = i2c_get_adapter(pdata->deferred_nr);
+ if (!deferred_adap)
+ return -EPROBE_DEFER;
+ i2c_put_adapter(deferred_adap);
+
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index ef016e46544a..39d06dd1f63a 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -757,6 +757,8 @@ config TOPSTAR_LAPTOP
depends on ACPI
depends on INPUT
select INPUT_SPARSEKMAP
+ select LEDS_CLASS
+ select NEW_LEDS
---help---
This driver adds support for hotkeys found on Topstar laptops.
@@ -1174,6 +1176,7 @@ config INTEL_TELEMETRY
config MLX_PLATFORM
tristate "Mellanox Technologies platform support"
+ depends on I2C && REGMAP
---help---
This option enables system support for the Mellanox Technologies
platform. The Mellanox systems provide data center networking
diff --git a/drivers/platform/x86/dell-smbios-base.c b/drivers/platform/x86/dell-smbios-base.c
index 2485c80a9fdd..33fb2a20458a 100644
--- a/drivers/platform/x86/dell-smbios-base.c
+++ b/drivers/platform/x86/dell-smbios-base.c
@@ -514,7 +514,7 @@ static int build_tokens_sysfs(struct platform_device *dev)
continue;
loop_fail_create_value:
- kfree(value_name);
+ kfree(location_name);
goto out_unwind_strings;
}
smbios_attribute_group.attrs = token_attrs;
@@ -525,7 +525,7 @@ loop_fail_create_value:
return 0;
out_unwind_strings:
- for (i = i-1; i > 0; i--) {
+ while (i--) {
kfree(token_location_attrs[i].attr.name);
kfree(token_value_attrs[i].attr.name);
}
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 2cfbd3fa5136..cd95b6f3a064 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -53,6 +53,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <linux/bitops.h>
#include <linux/dmi.h>
#include <linux/backlight.h>
#include <linux/fb.h>
@@ -61,12 +62,11 @@
#include <linux/kfifo.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
-#include <linux/slab.h>
#include <acpi/video.h>
-#define FUJITSU_DRIVER_VERSION "0.6.0"
+#define FUJITSU_DRIVER_VERSION "0.6.0"
-#define FUJITSU_LCD_N_LEVELS 8
+#define FUJITSU_LCD_N_LEVELS 8
#define ACPI_FUJITSU_CLASS "fujitsu"
#define ACPI_FUJITSU_BL_HID "FUJ02B1"
@@ -76,41 +76,51 @@
#define ACPI_FUJITSU_LAPTOP_DRIVER_NAME "Fujitsu laptop FUJ02E3 ACPI hotkeys driver"
#define ACPI_FUJITSU_LAPTOP_DEVICE_NAME "Fujitsu FUJ02E3"
-#define ACPI_FUJITSU_NOTIFY_CODE1 0x80
+#define ACPI_FUJITSU_NOTIFY_CODE 0x80
/* FUNC interface - command values */
-#define FUNC_FLAGS 0x1000
-#define FUNC_LEDS 0x1001
-#define FUNC_BUTTONS 0x1002
-#define FUNC_BACKLIGHT 0x1004
+#define FUNC_FLAGS BIT(12)
+#define FUNC_LEDS (BIT(12) | BIT(0))
+#define FUNC_BUTTONS (BIT(12) | BIT(1))
+#define FUNC_BACKLIGHT (BIT(12) | BIT(2))
/* FUNC interface - responses */
-#define UNSUPPORTED_CMD 0x80000000
+#define UNSUPPORTED_CMD 0x80000000
/* FUNC interface - status flags */
-#define FLAG_RFKILL 0x020
-#define FLAG_LID 0x100
-#define FLAG_DOCK 0x200
+#define FLAG_RFKILL BIT(5)
+#define FLAG_LID BIT(8)
+#define FLAG_DOCK BIT(9)
/* FUNC interface - LED control */
-#define FUNC_LED_OFF 0x1
-#define FUNC_LED_ON 0x30001
-#define KEYBOARD_LAMPS 0x100
-#define LOGOLAMP_POWERON 0x2000
-#define LOGOLAMP_ALWAYS 0x4000
-#define RADIO_LED_ON 0x20
-#define ECO_LED 0x10000
-#define ECO_LED_ON 0x80000
-
-/* Hotkey details */
-#define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */
-#define KEY2_CODE 0x411
-#define KEY3_CODE 0x412
-#define KEY4_CODE 0x413
-#define KEY5_CODE 0x420
-
-#define MAX_HOTKEY_RINGBUFFER_SIZE 100
-#define RINGBUFFERSIZE 40
+#define FUNC_LED_OFF BIT(0)
+#define FUNC_LED_ON (BIT(0) | BIT(16) | BIT(17))
+#define LOGOLAMP_POWERON BIT(13)
+#define LOGOLAMP_ALWAYS BIT(14)
+#define KEYBOARD_LAMPS BIT(8)
+#define RADIO_LED_ON BIT(5)
+#define ECO_LED BIT(16)
+#define ECO_LED_ON BIT(19)
+
+/* FUNC interface - backlight power control */
+#define BACKLIGHT_PARAM_POWER BIT(2)
+#define BACKLIGHT_OFF (BIT(0) | BIT(1))
+#define BACKLIGHT_ON 0
+
+/* Scancodes read from the GIRB register */
+#define KEY1_CODE 0x410
+#define KEY2_CODE 0x411
+#define KEY3_CODE 0x412
+#define KEY4_CODE 0x413
+#define KEY5_CODE 0x420
+
+/* Hotkey ringbuffer limits */
+#define MAX_HOTKEY_RINGBUFFER_SIZE 100
+#define RINGBUFFERSIZE 40
+
+/* Module parameters */
+static int use_alt_lcd_levels = -1;
+static bool disable_brightness_adjust;
/* Device controlling the backlight and associated keys */
struct fujitsu_bl {
@@ -122,8 +132,6 @@ struct fujitsu_bl {
};
static struct fujitsu_bl *fujitsu_bl;
-static int use_alt_lcd_levels = -1;
-static bool disable_brightness_adjust;
/* Device used to access hotkeys and other features on the laptop */
struct fujitsu_laptop {
@@ -256,9 +264,11 @@ static int bl_update_status(struct backlight_device *b)
if (fext) {
if (b->props.power == FB_BLANK_POWERDOWN)
- call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x3);
+ call_fext_func(fext, FUNC_BACKLIGHT, 0x1,
+ BACKLIGHT_PARAM_POWER, BACKLIGHT_OFF);
else
- call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x0);
+ call_fext_func(fext, FUNC_BACKLIGHT, 0x1,
+ BACKLIGHT_PARAM_POWER, BACKLIGHT_ON);
}
return set_lcd_level(device, b->props.brightness);
@@ -385,7 +395,7 @@ static int fujitsu_backlight_register(struct acpi_device *device)
static int acpi_fujitsu_bl_add(struct acpi_device *device)
{
struct fujitsu_bl *priv;
- int error;
+ int ret;
if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
return -ENODEV;
@@ -399,10 +409,6 @@ static int acpi_fujitsu_bl_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_FUJITSU_CLASS);
device->driver_data = priv;
- error = acpi_fujitsu_bl_input_setup(device);
- if (error)
- return error;
-
pr_info("ACPI: %s [%s]\n",
acpi_device_name(device), acpi_device_bid(device));
@@ -410,11 +416,11 @@ static int acpi_fujitsu_bl_add(struct acpi_device *device)
priv->max_brightness = FUJITSU_LCD_N_LEVELS;
get_lcd_level(device);
- error = fujitsu_backlight_register(device);
- if (error)
- return error;
+ ret = acpi_fujitsu_bl_input_setup(device);
+ if (ret)
+ return ret;
- return 0;
+ return fujitsu_backlight_register(device);
}
/* Brightness notify */
@@ -424,7 +430,7 @@ static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event)
struct fujitsu_bl *priv = acpi_driver_data(device);
int oldb, newb;
- if (event != ACPI_FUJITSU_NOTIFY_CODE1) {
+ if (event != ACPI_FUJITSU_NOTIFY_CODE) {
acpi_handle_info(device->handle, "unsupported event [0x%x]\n",
event);
sparse_keymap_report_event(priv->input, -1, 1, true);
@@ -455,7 +461,9 @@ static const struct key_entry keymap_default[] = {
{ KE_KEY, KEY3_CODE, { KEY_PROG3 } },
{ KE_KEY, KEY4_CODE, { KEY_PROG4 } },
{ KE_KEY, KEY5_CODE, { KEY_RFKILL } },
+ { KE_KEY, BIT(5), { KEY_RFKILL } },
{ KE_KEY, BIT(26), { KEY_TOUCHPAD_TOGGLE } },
+ { KE_KEY, BIT(29), { KEY_MICMUTE } },
{ KE_END, 0 }
};
@@ -693,7 +701,7 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
{
struct fujitsu_laptop *priv = acpi_driver_data(device);
struct led_classdev *led;
- int result;
+ int ret;
if (call_fext_func(device,
FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) {
@@ -704,9 +712,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
led->name = "fujitsu::logolamp";
led->brightness_set_blocking = logolamp_set;
led->brightness_get = logolamp_get;
- result = devm_led_classdev_register(&device->dev, led);
- if (result)
- return result;
+ ret = devm_led_classdev_register(&device->dev, led);
+ if (ret)
+ return ret;
}
if ((call_fext_func(device,
@@ -719,9 +727,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
led->name = "fujitsu::kblamps";
led->brightness_set_blocking = kblamps_set;
led->brightness_get = kblamps_get;
- result = devm_led_classdev_register(&device->dev, led);
- if (result)
- return result;
+ ret = devm_led_classdev_register(&device->dev, led);
+ if (ret)
+ return ret;
}
/*
@@ -742,9 +750,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
led->brightness_set_blocking = radio_led_set;
led->brightness_get = radio_led_get;
led->default_trigger = "rfkill-any";
- result = devm_led_classdev_register(&device->dev, led);
- if (result)
- return result;
+ ret = devm_led_classdev_register(&device->dev, led);
+ if (ret)
+ return ret;
}
/* Support for eco led is not always signaled in bit corresponding
@@ -762,9 +770,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
led->name = "fujitsu::eco_led";
led->brightness_set_blocking = eco_led_set;
led->brightness_get = eco_led_get;
- result = devm_led_classdev_register(&device->dev, led);
- if (result)
- return result;
+ ret = devm_led_classdev_register(&device->dev, led);
+ if (ret)
+ return ret;
}
return 0;
@@ -773,8 +781,7 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
static int acpi_fujitsu_laptop_add(struct acpi_device *device)
{
struct fujitsu_laptop *priv;
- int error;
- int i;
+ int ret, i = 0;
priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -789,23 +796,16 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device)
/* kfifo */
spin_lock_init(&priv->fifo_lock);
- error = kfifo_alloc(&priv->fifo, RINGBUFFERSIZE * sizeof(int),
- GFP_KERNEL);
- if (error) {
- pr_err("kfifo_alloc failed\n");
- goto err_stop;
- }
-
- error = acpi_fujitsu_laptop_input_setup(device);
- if (error)
- goto err_free_fifo;
+ ret = kfifo_alloc(&priv->fifo, RINGBUFFERSIZE * sizeof(int),
+ GFP_KERNEL);
+ if (ret)
+ return ret;
pr_info("ACPI: %s [%s]\n",
acpi_device_name(device), acpi_device_bid(device));
- i = 0;
- while (call_fext_func(device, FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0
- && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE)
+ while (call_fext_func(device, FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0 &&
+ i++ < MAX_HOTKEY_RINGBUFFER_SIZE)
; /* No action, result is discarded */
acpi_handle_debug(device->handle, "Discarded %i ringbuffer entries\n",
i);
@@ -829,26 +829,31 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device)
/* Sync backlight power status */
if (fujitsu_bl && fujitsu_bl->bl_device &&
acpi_video_get_backlight_type() == acpi_backlight_vendor) {
- if (call_fext_func(fext, FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3)
+ if (call_fext_func(fext, FUNC_BACKLIGHT, 0x2,
+ BACKLIGHT_PARAM_POWER, 0x0) == BACKLIGHT_OFF)
fujitsu_bl->bl_device->props.power = FB_BLANK_POWERDOWN;
else
fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK;
}
- error = acpi_fujitsu_laptop_leds_register(device);
- if (error)
+ ret = acpi_fujitsu_laptop_input_setup(device);
+ if (ret)
+ goto err_free_fifo;
+
+ ret = acpi_fujitsu_laptop_leds_register(device);
+ if (ret)
goto err_free_fifo;
- error = fujitsu_laptop_platform_add(device);
- if (error)
+ ret = fujitsu_laptop_platform_add(device);
+ if (ret)
goto err_free_fifo;
return 0;
err_free_fifo:
kfifo_free(&priv->fifo);
-err_stop:
- return error;
+
+ return ret;
}
static int acpi_fujitsu_laptop_remove(struct acpi_device *device)
@@ -865,11 +870,11 @@ static int acpi_fujitsu_laptop_remove(struct acpi_device *device)
static void acpi_fujitsu_laptop_press(struct acpi_device *device, int scancode)
{
struct fujitsu_laptop *priv = acpi_driver_data(device);
- int status;
+ int ret;
- status = kfifo_in_locked(&priv->fifo, (unsigned char *)&scancode,
- sizeof(scancode), &priv->fifo_lock);
- if (status != sizeof(scancode)) {
+ ret = kfifo_in_locked(&priv->fifo, (unsigned char *)&scancode,
+ sizeof(scancode), &priv->fifo_lock);
+ if (ret != sizeof(scancode)) {
dev_info(&priv->input->dev, "Could not push scancode [0x%x]\n",
scancode);
return;
@@ -882,13 +887,12 @@ static void acpi_fujitsu_laptop_press(struct acpi_device *device, int scancode)
static void acpi_fujitsu_laptop_release(struct acpi_device *device)
{
struct fujitsu_laptop *priv = acpi_driver_data(device);
- int scancode, status;
+ int scancode, ret;
while (true) {
- status = kfifo_out_locked(&priv->fifo,
- (unsigned char *)&scancode,
- sizeof(scancode), &priv->fifo_lock);
- if (status != sizeof(scancode))
+ ret = kfifo_out_locked(&priv->fifo, (unsigned char *)&scancode,
+ sizeof(scancode), &priv->fifo_lock);
+ if (ret != sizeof(scancode))
return;
sparse_keymap_report_event(priv->input, scancode, 0, false);
dev_dbg(&priv->input->dev,
@@ -899,10 +903,10 @@ static void acpi_fujitsu_laptop_release(struct acpi_device *device)
static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
{
struct fujitsu_laptop *priv = acpi_driver_data(device);
- int scancode, i = 0;
+ int scancode, i = 0, ret;
unsigned int irb;
- if (event != ACPI_FUJITSU_NOTIFY_CODE1) {
+ if (event != ACPI_FUJITSU_NOTIFY_CODE) {
acpi_handle_info(device->handle, "Unsupported event [0x%x]\n",
event);
sparse_keymap_report_event(priv->input, -1, 1, true);
@@ -930,9 +934,18 @@ static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
* E736/E746/E756), the touchpad toggle hotkey (Fn+F4) is
* handled in software; its state is queried using FUNC_FLAGS
*/
- if ((priv->flags_supported & BIT(26)) &&
- (call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0) & BIT(26)))
- sparse_keymap_report_event(priv->input, BIT(26), 1, true);
+ if (priv->flags_supported & (BIT(5) | BIT(26) | BIT(29))) {
+ ret = call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0);
+ if (ret & BIT(5))
+ sparse_keymap_report_event(priv->input,
+ BIT(5), 1, true);
+ if (ret & BIT(26))
+ sparse_keymap_report_event(priv->input,
+ BIT(26), 1, true);
+ if (ret & BIT(29))
+ sparse_keymap_report_event(priv->input,
+ BIT(29), 1, true);
+ }
}
/* Initialization */
diff --git a/drivers/platform/x86/gpd-pocket-fan.c b/drivers/platform/x86/gpd-pocket-fan.c
index 2d645c505f81..be85ed966bf3 100644
--- a/drivers/platform/x86/gpd-pocket-fan.c
+++ b/drivers/platform/x86/gpd-pocket-fan.c
@@ -19,12 +19,12 @@
static int temp_limits[3] = { 55000, 60000, 65000 };
module_param_array(temp_limits, int, NULL, 0444);
MODULE_PARM_DESC(temp_limits,
- "Milli-celcius values above which the fan speed increases");
+ "Millicelsius values above which the fan speed increases");
static int hysteresis = 3000;
module_param(hysteresis, int, 0444);
MODULE_PARM_DESC(hysteresis,
- "Hysteresis in milli-celcius before lowering the fan speed");
+ "Hysteresis in millicelsius before lowering the fan speed");
static int speed_on_ac = 2;
module_param(speed_on_ac, int, 0444);
diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c
index 5e3df194723e..b5adba227783 100644
--- a/drivers/platform/x86/intel-hid.c
+++ b/drivers/platform/x86/intel-hid.c
@@ -16,16 +16,14 @@
*
*/
+#include <linux/acpi.h>
+#include <linux/dmi.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/input.h>
#include <linux/platform_device.h>
-#include <linux/input/sparse-keymap.h>
-#include <linux/acpi.h>
#include <linux/suspend.h>
-#include <acpi/acpi_bus.h>
-#include <linux/dmi.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex Hung");
@@ -67,8 +65,8 @@ static const struct key_entry intel_array_keymap[] = {
{ KE_IGNORE, 0xC5, { KEY_VOLUMEUP } }, /* Release */
{ KE_KEY, 0xC6, { KEY_VOLUMEDOWN } }, /* Press */
{ KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* Release */
- { KE_SW, 0xC8, { .sw = { SW_ROTATE_LOCK, 1 } } }, /* Press */
- { KE_SW, 0xC9, { .sw = { SW_ROTATE_LOCK, 0 } } }, /* Release */
+ { KE_KEY, 0xC8, { KEY_ROTATE_LOCK_TOGGLE } }, /* Press */
+ { KE_IGNORE, 0xC9, { KEY_ROTATE_LOCK_TOGGLE } }, /* Release */
{ KE_KEY, 0xCE, { KEY_POWER } }, /* Press */
{ KE_IGNORE, 0xCF, { KEY_POWER } }, /* Release */
{ KE_END },
diff --git a/drivers/platform/x86/intel_turbo_max_3.c b/drivers/platform/x86/intel_turbo_max_3.c
index d4ea01805879..a6d5aa0c3c47 100644
--- a/drivers/platform/x86/intel_turbo_max_3.c
+++ b/drivers/platform/x86/intel_turbo_max_3.c
@@ -138,9 +138,6 @@ static int __init itmt_legacy_init(void)
if (!id)
return -ENODEV;
- if (boot_cpu_has(X86_FEATURE_HWP))
- return -ENODEV;
-
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"platform/x86/turbo_max_3:online",
itmt_legacy_cpu_online, NULL);
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index 454e14f02285..7a0bd24c1ae2 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -85,6 +85,15 @@
#define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0)
#define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0)
+/* Default I2C parent bus number */
+#define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1
+
+/* Maximum number of possible physical buses equipped on system */
+#define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM 16
+
+/* Number of channels in group */
+#define MLXPLAT_CPLD_GRP_CHNL_NUM 8
+
/* Start channel numbers */
#define MLXPLAT_CPLD_CH1 2
#define MLXPLAT_CPLD_CH2 10
@@ -124,7 +133,7 @@ static const struct resource mlxplat_lpc_resources[] = {
};
/* Platform default channels */
-static const int mlxplat_default_channels[][8] = {
+static const int mlxplat_default_channels[][MLXPLAT_CPLD_GRP_CHNL_NUM] = {
{
MLXPLAT_CPLD_CH1, MLXPLAT_CPLD_CH1 + 1, MLXPLAT_CPLD_CH1 + 2,
MLXPLAT_CPLD_CH1 + 3, MLXPLAT_CPLD_CH1 + 4, MLXPLAT_CPLD_CH1 +
@@ -694,6 +703,8 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
ARRAY_SIZE(mlxplat_default_channels[i]);
}
mlxplat_hotplug = &mlxplat_mlxcpld_default_data;
+ mlxplat_hotplug->deferred_nr =
+ mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
return 1;
};
@@ -708,6 +719,8 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
ARRAY_SIZE(mlxplat_msn21xx_channels);
}
mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data;
+ mlxplat_hotplug->deferred_nr =
+ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
return 1;
};
@@ -722,6 +735,8 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
ARRAY_SIZE(mlxplat_msn21xx_channels);
}
mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data;
+ mlxplat_hotplug->deferred_nr =
+ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
return 1;
};
@@ -736,6 +751,8 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
ARRAY_SIZE(mlxplat_msn21xx_channels);
}
mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data;
+ mlxplat_hotplug->deferred_nr =
+ mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
return 1;
};
@@ -750,6 +767,8 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
ARRAY_SIZE(mlxplat_msn21xx_channels);
}
mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data;
+ mlxplat_hotplug->deferred_nr =
+ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
return 1;
};
@@ -830,10 +849,48 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
MODULE_DEVICE_TABLE(dmi, mlxplat_dmi_table);
+static int mlxplat_mlxcpld_verify_bus_topology(int *nr)
+{
+ struct i2c_adapter *search_adap;
+ int shift, i;
+
+ /* Scan adapters from expected id to verify it is free. */
+ *nr = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR;
+ for (i = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; i <
+ MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; i++) {
+ search_adap = i2c_get_adapter(i);
+ if (search_adap) {
+ i2c_put_adapter(search_adap);
+ continue;
+ }
+
+ /* Return if expected parent adapter is free. */
+ if (i == MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR)
+ return 0;
+ break;
+ }
+
+ /* Return with error if free id for adapter is not found. */
+ if (i == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM)
+ return -ENODEV;
+
+ /* Shift adapter ids, since expected parent adapter is not free. */
+ *nr = i;
+ for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
+ shift = *nr - mlxplat_mux_data[i].parent;
+ mlxplat_mux_data[i].parent = *nr;
+ mlxplat_mux_data[i].base_nr += shift;
+ if (shift > 0)
+ mlxplat_hotplug->shift_nr = shift;
+ }
+
+ return 0;
+}
+
static int __init mlxplat_init(void)
{
struct mlxplat_priv *priv;
- int i, err;
+ int i, nr, err;
if (!dmi_check_system(mlxplat_dmi_table))
return -ENODEV;
@@ -853,7 +910,12 @@ static int __init mlxplat_init(void)
}
platform_set_drvdata(mlxplat_dev, priv);
- priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", -1,
+ err = mlxplat_mlxcpld_verify_bus_topology(&nr);
+ if (nr < 0)
+ goto fail_alloc;
+
+ nr = (nr == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) ? -1 : nr;
+ priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", nr,
NULL, 0);
if (IS_ERR(priv->pdev_i2c)) {
err = PTR_ERR(priv->pdev_i2c);
diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c
index 3a624090191d..452aacabaa8e 100644
--- a/drivers/platform/x86/silead_dmi.c
+++ b/drivers/platform/x86/silead_dmi.c
@@ -446,6 +446,23 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "X3 Plus"),
},
},
+ {
+ /* I.T.Works TW701 */
+ .driver_data = (void *)&surftab_wintron70_st70416_6_data,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "i71c"),
+ DMI_MATCH(DMI_BIOS_VERSION, "itWORKS.G.WI71C.JGBMRB"),
+ },
+ },
+ {
+ /* Yours Y8W81, same case and touchscreen as Chuwi Vi8 */
+ .driver_data = (void *)&chuwi_vi8_data,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "YOURS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
+ },
+ },
{ },
};
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 1c57ee2b6d19..da1ca4856ea1 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -8703,16 +8703,24 @@ static const struct attribute_group fan_attr_group = {
.ec = TPID(__id1, __id2), \
.quirks = __quirks }
+#define TPACPI_FAN_QB(__id1, __id2, __quirks) \
+ { .vendor = PCI_VENDOR_ID_LENOVO, \
+ .bios = TPID(__id1, __id2), \
+ .ec = TPACPI_MATCH_ANY, \
+ .quirks = __quirks }
+
static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
TPACPI_FAN_QI('1', 'Y', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '8', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '6', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '0', TPACPI_FAN_Q1),
TPACPI_FAN_QL('7', 'M', TPACPI_FAN_2FAN),
+ TPACPI_FAN_QB('N', '1', TPACPI_FAN_2FAN),
};
#undef TPACPI_FAN_QL
#undef TPACPI_FAN_QI
+#undef TPACPI_FAN_QB
static int __init fan_init(struct ibm_init_struct *iibm)
{
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index 1032c00b907b..f7761d98c0fd 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -1,14 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * ACPI driver for Topstar notebooks (hotkeys support only)
+ * Topstar Laptop ACPI Extras driver
*
* Copyright (c) 2009 Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ * Copyright (c) 2018 Guillaume Douézan-Grard
*
* Implementation inspired by existing x86 platform drivers, in special
- * asus/eepc/fujitsu-laptop, thanks to their authors
- *
- * 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.
+ * asus/eepc/fujitsu-laptop, thanks to their authors.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -18,15 +16,93 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/acpi.h>
+#include <linux/dmi.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
-#define ACPI_TOPSTAR_CLASS "topstar"
+#define TOPSTAR_LAPTOP_CLASS "topstar"
-struct topstar_hkey {
- struct input_dev *inputdev;
+struct topstar_laptop {
+ struct acpi_device *device;
+ struct platform_device *platform;
+ struct input_dev *input;
+ struct led_classdev led;
};
+/*
+ * LED
+ */
+
+static enum led_brightness topstar_led_get(struct led_classdev *led)
+{
+ return led->brightness;
+}
+
+static int topstar_led_set(struct led_classdev *led,
+ enum led_brightness state)
+{
+ struct topstar_laptop *topstar = container_of(led,
+ struct topstar_laptop, led);
+
+ struct acpi_object_list params;
+ union acpi_object in_obj;
+ unsigned long long int ret;
+ acpi_status status;
+
+ params.count = 1;
+ params.pointer = &in_obj;
+ in_obj.type = ACPI_TYPE_INTEGER;
+ in_obj.integer.value = 0x83;
+
+ /*
+ * Topstar ACPI returns 0x30001 when the LED is ON and 0x30000 when it
+ * is OFF.
+ */
+ status = acpi_evaluate_integer(topstar->device->handle,
+ "GETX", &params, &ret);
+ if (ACPI_FAILURE(status))
+ return -1;
+
+ /*
+ * FNCX(0x83) toggles the LED (more precisely, it is supposed to
+ * act as an hardware switch and disconnect the WLAN adapter but
+ * it seems to be faulty on some models like the Topstar U931
+ * Notebook).
+ */
+ if ((ret == 0x30001 && state == LED_OFF)
+ || (ret == 0x30000 && state != LED_OFF)) {
+ status = acpi_execute_simple_method(topstar->device->handle,
+ "FNCX", 0x83);
+ if (ACPI_FAILURE(status))
+ return -1;
+ }
+
+ return 0;
+}
+
+static int topstar_led_init(struct topstar_laptop *topstar)
+{
+ topstar->led = (struct led_classdev) {
+ .default_trigger = "rfkill0",
+ .brightness_get = topstar_led_get,
+ .brightness_set_blocking = topstar_led_set,
+ .name = TOPSTAR_LAPTOP_CLASS "::wlan",
+ };
+
+ return led_classdev_register(&topstar->platform->dev, &topstar->led);
+}
+
+static void topstar_led_exit(struct topstar_laptop *topstar)
+{
+ led_classdev_unregister(&topstar->led);
+}
+
+/*
+ * Input
+ */
+
static const struct key_entry topstar_keymap[] = {
{ KE_KEY, 0x80, { KEY_BRIGHTNESSUP } },
{ KE_KEY, 0x81, { KEY_BRIGHTNESSDOWN } },
@@ -57,107 +133,217 @@ static const struct key_entry topstar_keymap[] = {
{ KE_END, 0 }
};
-static void acpi_topstar_notify(struct acpi_device *device, u32 event)
+static void topstar_input_notify(struct topstar_laptop *topstar, int event)
{
- static bool dup_evnt[2];
- bool *dup;
- struct topstar_hkey *hkey = acpi_driver_data(device);
-
- /* 0x83 and 0x84 key events comes duplicated... */
- if (event == 0x83 || event == 0x84) {
- dup = &dup_evnt[event - 0x83];
- if (*dup) {
- *dup = false;
- return;
- }
- *dup = true;
- }
-
- if (!sparse_keymap_report_event(hkey->inputdev, event, 1, true))
+ if (!sparse_keymap_report_event(topstar->input, event, 1, true))
pr_info("unknown event = 0x%02x\n", event);
}
-static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
-{
- acpi_status status;
-
- status = acpi_execute_simple_method(device->handle, "FNCX",
- state ? 0x86 : 0x87);
- if (ACPI_FAILURE(status)) {
- pr_err("Unable to switch FNCX notifications\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static int acpi_topstar_init_hkey(struct topstar_hkey *hkey)
+static int topstar_input_init(struct topstar_laptop *topstar)
{
struct input_dev *input;
- int error;
+ int err;
input = input_allocate_device();
if (!input)
return -ENOMEM;
input->name = "Topstar Laptop extra buttons";
- input->phys = "topstar/input0";
+ input->phys = TOPSTAR_LAPTOP_CLASS "/input0";
input->id.bustype = BUS_HOST;
+ input->dev.parent = &topstar->platform->dev;
- error = sparse_keymap_setup(input, topstar_keymap, NULL);
- if (error) {
+ err = sparse_keymap_setup(input, topstar_keymap, NULL);
+ if (err) {
pr_err("Unable to setup input device keymap\n");
goto err_free_dev;
}
- error = input_register_device(input);
- if (error) {
+ err = input_register_device(input);
+ if (err) {
pr_err("Unable to register input device\n");
goto err_free_dev;
}
- hkey->inputdev = input;
+ topstar->input = input;
return 0;
- err_free_dev:
+err_free_dev:
input_free_device(input);
- return error;
+ return err;
}
-static int acpi_topstar_add(struct acpi_device *device)
+static void topstar_input_exit(struct topstar_laptop *topstar)
{
- struct topstar_hkey *tps_hkey;
+ input_unregister_device(topstar->input);
+}
- tps_hkey = kzalloc(sizeof(struct topstar_hkey), GFP_KERNEL);
- if (!tps_hkey)
+/*
+ * Platform
+ */
+
+static struct platform_driver topstar_platform_driver = {
+ .driver = {
+ .name = TOPSTAR_LAPTOP_CLASS,
+ },
+};
+
+static int topstar_platform_init(struct topstar_laptop *topstar)
+{
+ int err;
+
+ topstar->platform = platform_device_alloc(TOPSTAR_LAPTOP_CLASS, -1);
+ if (!topstar->platform)
return -ENOMEM;
- strcpy(acpi_device_name(device), "Topstar TPSACPI");
- strcpy(acpi_device_class(device), ACPI_TOPSTAR_CLASS);
+ platform_set_drvdata(topstar->platform, topstar);
+
+ err = platform_device_add(topstar->platform);
+ if (err)
+ goto err_device_put;
+
+ return 0;
- if (acpi_topstar_fncx_switch(device, true))
- goto add_err;
+err_device_put:
+ platform_device_put(topstar->platform);
+ return err;
+}
+
+static void topstar_platform_exit(struct topstar_laptop *topstar)
+{
+ platform_device_unregister(topstar->platform);
+}
+
+/*
+ * ACPI
+ */
+
+static int topstar_acpi_fncx_switch(struct acpi_device *device, bool state)
+{
+ acpi_status status;
+ u64 arg = state ? 0x86 : 0x87;
- if (acpi_topstar_init_hkey(tps_hkey))
- goto add_err;
+ status = acpi_execute_simple_method(device->handle, "FNCX", arg);
+ if (ACPI_FAILURE(status)) {
+ pr_err("Unable to switch FNCX notifications\n");
+ return -ENODEV;
+ }
- device->driver_data = tps_hkey;
return 0;
+}
-add_err:
- kfree(tps_hkey);
- return -ENODEV;
+static void topstar_acpi_notify(struct acpi_device *device, u32 event)
+{
+ struct topstar_laptop *topstar = acpi_driver_data(device);
+ static bool dup_evnt[2];
+ bool *dup;
+
+ /* 0x83 and 0x84 key events comes duplicated... */
+ if (event == 0x83 || event == 0x84) {
+ dup = &dup_evnt[event - 0x83];
+ if (*dup) {
+ *dup = false;
+ return;
+ }
+ *dup = true;
+ }
+
+ topstar_input_notify(topstar, event);
}
-static int acpi_topstar_remove(struct acpi_device *device)
+static int topstar_acpi_init(struct topstar_laptop *topstar)
{
- struct topstar_hkey *tps_hkey = acpi_driver_data(device);
+ return topstar_acpi_fncx_switch(topstar->device, true);
+}
- acpi_topstar_fncx_switch(device, false);
+static void topstar_acpi_exit(struct topstar_laptop *topstar)
+{
+ topstar_acpi_fncx_switch(topstar->device, false);
+}
- input_unregister_device(tps_hkey->inputdev);
- kfree(tps_hkey);
+/*
+ * Enable software-based WLAN LED control on systems with defective
+ * hardware switch.
+ */
+static bool led_workaround;
+static int dmi_led_workaround(const struct dmi_system_id *id)
+{
+ led_workaround = true;
+ return 0;
+}
+
+static const struct dmi_system_id topstar_dmi_ids[] = {
+ {
+ .callback = dmi_led_workaround,
+ .ident = "Topstar U931/RVP7",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "U931"),
+ DMI_MATCH(DMI_BOARD_VERSION, "RVP7"),
+ },
+ },
+ {}
+};
+
+static int topstar_acpi_add(struct acpi_device *device)
+{
+ struct topstar_laptop *topstar;
+ int err;
+
+ dmi_check_system(topstar_dmi_ids);
+
+ topstar = kzalloc(sizeof(struct topstar_laptop), GFP_KERNEL);
+ if (!topstar)
+ return -ENOMEM;
+
+ strcpy(acpi_device_name(device), "Topstar TPSACPI");
+ strcpy(acpi_device_class(device), TOPSTAR_LAPTOP_CLASS);
+ device->driver_data = topstar;
+ topstar->device = device;
+
+ err = topstar_acpi_init(topstar);
+ if (err)
+ goto err_free;
+
+ err = topstar_platform_init(topstar);
+ if (err)
+ goto err_acpi_exit;
+
+ err = topstar_input_init(topstar);
+ if (err)
+ goto err_platform_exit;
+
+ if (led_workaround) {
+ err = topstar_led_init(topstar);
+ if (err)
+ goto err_input_exit;
+ }
+
+ return 0;
+
+err_input_exit:
+ topstar_input_exit(topstar);
+err_platform_exit:
+ topstar_platform_exit(topstar);
+err_acpi_exit:
+ topstar_acpi_exit(topstar);
+err_free:
+ kfree(topstar);
+ return err;
+}
+
+static int topstar_acpi_remove(struct acpi_device *device)
+{
+ struct topstar_laptop *topstar = acpi_driver_data(device);
+
+ if (led_workaround)
+ topstar_led_exit(topstar);
+
+ topstar_input_exit(topstar);
+ topstar_platform_exit(topstar);
+ topstar_acpi_exit(topstar);
+
+ kfree(topstar);
return 0;
}
@@ -168,18 +354,47 @@ static const struct acpi_device_id topstar_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, topstar_device_ids);
-static struct acpi_driver acpi_topstar_driver = {
+static struct acpi_driver topstar_acpi_driver = {
.name = "Topstar laptop ACPI driver",
- .class = ACPI_TOPSTAR_CLASS,
+ .class = TOPSTAR_LAPTOP_CLASS,
.ids = topstar_device_ids,
.ops = {
- .add = acpi_topstar_add,
- .remove = acpi_topstar_remove,
- .notify = acpi_topstar_notify,
+ .add = topstar_acpi_add,
+ .remove = topstar_acpi_remove,
+ .notify = topstar_acpi_notify,
},
};
-module_acpi_driver(acpi_topstar_driver);
+
+static int __init topstar_laptop_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&topstar_platform_driver);
+ if (ret < 0)
+ return ret;
+
+ ret = acpi_bus_register_driver(&topstar_acpi_driver);
+ if (ret < 0)
+ goto err_driver_unreg;
+
+ pr_info("ACPI extras driver loaded\n");
+ return 0;
+
+err_driver_unreg:
+ platform_driver_unregister(&topstar_platform_driver);
+ return ret;
+}
+
+static void __exit topstar_laptop_exit(void)
+{
+ acpi_bus_unregister_driver(&topstar_acpi_driver);
+ platform_driver_unregister(&topstar_platform_driver);
+}
+
+module_init(topstar_laptop_init);
+module_exit(topstar_laptop_exit);
MODULE_AUTHOR("Herton Ronaldo Krzesinski");
+MODULE_AUTHOR("Guillaume Douézan-Grard");
MODULE_DESCRIPTION("Topstar Laptop ACPI Extras driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 8796211ef24a..8e3d0146ff8c 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -130,13 +130,11 @@ static bool find_guid(const char *guid_string, struct wmi_block **out)
uuid_le guid_input;
struct wmi_block *wblock;
struct guid_block *block;
- struct list_head *p;
if (uuid_le_to_bin(guid_string, &guid_input))
return false;
- list_for_each(p, &wmi_block_list) {
- wblock = list_entry(p, struct wmi_block, list);
+ list_for_each_entry(wblock, &wmi_block_list, list) {
block = &wblock->gblock;
if (memcmp(block->guid, &guid_input, 16) == 0) {
@@ -519,7 +517,6 @@ wmi_notify_handler handler, void *data)
struct wmi_block *block;
acpi_status status = AE_NOT_EXIST;
uuid_le guid_input;
- struct list_head *p;
if (!guid || !handler)
return AE_BAD_PARAMETER;
@@ -527,9 +524,8 @@ wmi_notify_handler handler, void *data)
if (uuid_le_to_bin(guid, &guid_input))
return AE_BAD_PARAMETER;
- list_for_each(p, &wmi_block_list) {
+ list_for_each_entry(block, &wmi_block_list, list) {
acpi_status wmi_status;
- block = list_entry(p, struct wmi_block, list);
if (memcmp(block->gblock.guid, &guid_input, 16) == 0) {
if (block->handler &&
@@ -560,7 +556,6 @@ acpi_status wmi_remove_notify_handler(const char *guid)
struct wmi_block *block;
acpi_status status = AE_NOT_EXIST;
uuid_le guid_input;
- struct list_head *p;
if (!guid)
return AE_BAD_PARAMETER;
@@ -568,9 +563,8 @@ acpi_status wmi_remove_notify_handler(const char *guid)
if (uuid_le_to_bin(guid, &guid_input))
return AE_BAD_PARAMETER;
- list_for_each(p, &wmi_block_list) {
+ list_for_each_entry(block, &wmi_block_list, list) {
acpi_status wmi_status;
- block = list_entry(p, struct wmi_block, list);
if (memcmp(block->gblock.guid, &guid_input, 16) == 0) {
if (!block->handler ||
@@ -610,15 +604,13 @@ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
union acpi_object params[1];
struct guid_block *gblock;
struct wmi_block *wblock;
- struct list_head *p;
input.count = 1;
input.pointer = params;
params[0].type = ACPI_TYPE_INTEGER;
params[0].integer.value = event;
- list_for_each(p, &wmi_block_list) {
- wblock = list_entry(p, struct wmi_block, list);
+ list_for_each_entry(wblock, &wmi_block_list, list) {
gblock = &wblock->gblock;
if ((gblock->flags & ACPI_WMI_EVENT) &&
@@ -933,12 +925,11 @@ static int wmi_dev_probe(struct device *dev)
goto probe_failure;
}
- buf = kmalloc(strlen(wdriver->driver.name) + 5, GFP_KERNEL);
+ buf = kasprintf(GFP_KERNEL, "wmi/%s", wdriver->driver.name);
if (!buf) {
ret = -ENOMEM;
goto probe_string_failure;
}
- sprintf(buf, "wmi/%s", wdriver->driver.name);
wblock->char_dev.minor = MISC_DYNAMIC_MINOR;
wblock->char_dev.name = buf;
wblock->char_dev.fops = &wmi_fops;
@@ -1261,11 +1252,9 @@ static void acpi_wmi_notify_handler(acpi_handle handle, u32 event,
{
struct guid_block *block;
struct wmi_block *wblock;
- struct list_head *p;
bool found_it = false;
- list_for_each(p, &wmi_block_list) {
- wblock = list_entry(p, struct wmi_block, list);
+ list_for_each_entry(wblock, &wmi_block_list, list) {
block = &wblock->gblock;
if (wblock->acpi_device->handle == handle &&
diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c
index cfb54e01d758..9d27016c899e 100644
--- a/drivers/rapidio/devices/rio_mport_cdev.c
+++ b/drivers/rapidio/devices/rio_mport_cdev.c
@@ -212,7 +212,6 @@ struct mport_cdev_priv {
#ifdef CONFIG_RAPIDIO_DMA_ENGINE
struct dma_chan *dmach;
struct list_head async_list;
- struct list_head pend_list;
spinlock_t req_lock;
struct mutex dma_lock;
struct kref dma_ref;
@@ -258,8 +257,6 @@ static DECLARE_WAIT_QUEUE_HEAD(mport_cdev_wait);
static struct class *dev_class;
static dev_t dev_number;
-static struct workqueue_struct *dma_wq;
-
static void mport_release_mapping(struct kref *ref);
static int rio_mport_maint_rd(struct mport_cdev_priv *priv, void __user *arg,
@@ -539,6 +536,7 @@ static int maint_comptag_set(struct mport_cdev_priv *priv, void __user *arg)
#ifdef CONFIG_RAPIDIO_DMA_ENGINE
struct mport_dma_req {
+ struct kref refcount;
struct list_head node;
struct file *filp;
struct mport_cdev_priv *priv;
@@ -554,11 +552,6 @@ struct mport_dma_req {
struct completion req_comp;
};
-struct mport_faf_work {
- struct work_struct work;
- struct mport_dma_req *req;
-};
-
static void mport_release_def_dma(struct kref *dma_ref)
{
struct mport_dev *md =
@@ -578,8 +571,10 @@ static void mport_release_dma(struct kref *dma_ref)
complete(&priv->comp);
}
-static void dma_req_free(struct mport_dma_req *req)
+static void dma_req_free(struct kref *ref)
{
+ struct mport_dma_req *req = container_of(ref, struct mport_dma_req,
+ refcount);
struct mport_cdev_priv *priv = req->priv;
unsigned int i;
@@ -611,30 +606,7 @@ static void dma_xfer_callback(void *param)
req->status = dma_async_is_tx_complete(priv->dmach, req->cookie,
NULL, NULL);
complete(&req->req_comp);
-}
-
-static void dma_faf_cleanup(struct work_struct *_work)
-{
- struct mport_faf_work *work = container_of(_work,
- struct mport_faf_work, work);
- struct mport_dma_req *req = work->req;
-
- dma_req_free(req);
- kfree(work);
-}
-
-static void dma_faf_callback(void *param)
-{
- struct mport_dma_req *req = (struct mport_dma_req *)param;
- struct mport_faf_work *work;
-
- work = kmalloc(sizeof(*work), GFP_ATOMIC);
- if (!work)
- return;
-
- INIT_WORK(&work->work, dma_faf_cleanup);
- work->req = req;
- queue_work(dma_wq, &work->work);
+ kref_put(&req->refcount, dma_req_free);
}
/*
@@ -765,16 +737,14 @@ static int do_dma_request(struct mport_dma_req *req,
goto err_out;
}
- if (sync == RIO_TRANSFER_FAF)
- tx->callback = dma_faf_callback;
- else
- tx->callback = dma_xfer_callback;
+ tx->callback = dma_xfer_callback;
tx->callback_param = req;
req->dmach = chan;
req->sync = sync;
req->status = DMA_IN_PROGRESS;
init_completion(&req->req_comp);
+ kref_get(&req->refcount);
cookie = dmaengine_submit(tx);
req->cookie = cookie;
@@ -785,6 +755,7 @@ static int do_dma_request(struct mport_dma_req *req,
if (dma_submit_error(cookie)) {
rmcd_error("submit err=%d (addr:0x%llx len:0x%llx)",
cookie, xfer->rio_addr, xfer->length);
+ kref_put(&req->refcount, dma_req_free);
ret = -EIO;
goto err_out;
}
@@ -860,6 +831,8 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
if (!req)
return -ENOMEM;
+ kref_init(&req->refcount);
+
ret = get_dma_channel(priv);
if (ret) {
kfree(req);
@@ -968,42 +941,20 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
ret = do_dma_request(req, xfer, sync, nents);
if (ret >= 0) {
- if (sync == RIO_TRANSFER_SYNC)
- goto sync_out;
- return ret; /* return ASYNC cookie */
- }
-
- if (ret == -ETIMEDOUT || ret == -EINTR) {
- /*
- * This can happen only in case of SYNC transfer.
- * Do not free unfinished request structure immediately.
- * Place it into pending list and deal with it later
- */
- spin_lock(&priv->req_lock);
- list_add_tail(&req->node, &priv->pend_list);
- spin_unlock(&priv->req_lock);
- return ret;
+ if (sync == RIO_TRANSFER_ASYNC)
+ return ret; /* return ASYNC cookie */
+ } else {
+ rmcd_debug(DMA, "do_dma_request failed with err=%d", ret);
}
-
- rmcd_debug(DMA, "do_dma_request failed with err=%d", ret);
-sync_out:
- dma_unmap_sg(chan->device->dev, req->sgt.sgl, req->sgt.nents, dir);
- sg_free_table(&req->sgt);
err_pg:
- if (page_list) {
+ if (!req->page_list) {
for (i = 0; i < nr_pages; i++)
put_page(page_list[i]);
kfree(page_list);
}
err_req:
- if (req->map) {
- mutex_lock(&md->buf_mutex);
- kref_put(&req->map->ref, mport_release_mapping);
- mutex_unlock(&md->buf_mutex);
- }
- put_dma_channel(priv);
- kfree(req);
+ kref_put(&req->refcount, dma_req_free);
return ret;
}
@@ -1121,7 +1072,7 @@ static int rio_mport_wait_for_async_dma(struct file *filp, void __user *arg)
ret = 0;
if (req->status != DMA_IN_PROGRESS && req->status != DMA_PAUSED)
- dma_req_free(req);
+ kref_put(&req->refcount, dma_req_free);
return ret;
@@ -1966,7 +1917,6 @@ static int mport_cdev_open(struct inode *inode, struct file *filp)
#ifdef CONFIG_RAPIDIO_DMA_ENGINE
INIT_LIST_HEAD(&priv->async_list);
- INIT_LIST_HEAD(&priv->pend_list);
spin_lock_init(&priv->req_lock);
mutex_init(&priv->dma_lock);
#endif
@@ -2006,8 +1956,6 @@ static void mport_cdev_release_dma(struct file *filp)
md = priv->md;
- flush_workqueue(dma_wq);
-
spin_lock(&priv->req_lock);
if (!list_empty(&priv->async_list)) {
rmcd_debug(EXIT, "async list not empty filp=%p %s(%d)",
@@ -2023,20 +1971,7 @@ static void mport_cdev_release_dma(struct file *filp)
req->filp, req->cookie,
completion_done(&req->req_comp)?"yes":"no");
list_del(&req->node);
- dma_req_free(req);
- }
- }
-
- if (!list_empty(&priv->pend_list)) {
- rmcd_debug(EXIT, "Free pending DMA requests for filp=%p %s(%d)",
- filp, current->comm, task_pid_nr(current));
- list_for_each_entry_safe(req,
- req_next, &priv->pend_list, node) {
- rmcd_debug(EXIT, "free req->filp=%p cookie=%d compl=%s",
- req->filp, req->cookie,
- completion_done(&req->req_comp)?"yes":"no");
- list_del(&req->node);
- dma_req_free(req);
+ kref_put(&req->refcount, dma_req_free);
}
}
@@ -2048,15 +1983,6 @@ static void mport_cdev_release_dma(struct file *filp)
current->comm, task_pid_nr(current), wret);
}
- spin_lock(&priv->req_lock);
-
- if (!list_empty(&priv->pend_list)) {
- rmcd_debug(EXIT, "ATTN: pending DMA requests, filp=%p %s(%d)",
- filp, current->comm, task_pid_nr(current));
- }
-
- spin_unlock(&priv->req_lock);
-
if (priv->dmach != priv->md->dma_chan) {
rmcd_debug(EXIT, "Release DMA channel for filp=%p %s(%d)",
filp, current->comm, task_pid_nr(current));
@@ -2573,8 +2499,6 @@ static void mport_cdev_remove(struct mport_dev *md)
cdev_device_del(&md->cdev, &md->dev);
mport_cdev_kill_fasync(md);
- flush_workqueue(dma_wq);
-
/* TODO: do we need to give clients some time to close file
* descriptors? Simple wait for XX, or kref?
*/
@@ -2691,17 +2615,8 @@ static int __init mport_init(void)
goto err_cli;
}
- dma_wq = create_singlethread_workqueue("dma_wq");
- if (!dma_wq) {
- rmcd_error("failed to create DMA work queue");
- ret = -ENOMEM;
- goto err_wq;
- }
-
return 0;
-err_wq:
- class_interface_unregister(&rio_mport_interface);
err_cli:
unregister_chrdev_region(dev_number, RIO_MAX_MPORTS);
err_chr:
@@ -2717,7 +2632,6 @@ static void __exit mport_exit(void)
class_interface_unregister(&rio_mport_interface);
class_destroy(dev_class);
unregister_chrdev_region(dev_number, RIO_MAX_MPORTS);
- destroy_workqueue(dma_wq);
}
module_init(mport_init);
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 23429bdaca84..161b927d9de1 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -76,7 +76,7 @@ static u16 rio_destid_alloc(struct rio_net *net)
}
/**
- * rio_destid_reserve - Reserve the specivied destID
+ * rio_destid_reserve - Reserve the specified destID
* @net: RIO network
* @destid: destID to reserve
*
@@ -885,7 +885,7 @@ static struct rio_net *rio_scan_alloc_net(struct rio_mport *mport,
*
* For each enumerated device, ensure that each switch in a system
* has correct routing entries. Add routes for devices that where
- * unknown dirung the first enumeration pass through the switch.
+ * unknown during the first enumeration pass through the switch.
*/
static void rio_update_route_tables(struct rio_net *net)
{
@@ -983,7 +983,7 @@ static int rio_enum_mport(struct rio_mport *mport, u32 flags)
/* reserve mport destID in new net */
rio_destid_reserve(net, mport->host_deviceid);
- /* Enable Input Output Port (transmitter reviever) */
+ /* Enable Input Output Port (transmitter receiver) */
rio_enable_rx_tx_port(mport, 1, 0, 0, 0);
/* Set component tag for host */
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index b609e1d3654b..027274008b08 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -6,6 +6,7 @@ config REMOTEPROC
select CRC32
select FW_LOADER
select VIRTIO
+ select WANT_DEV_COREDUMP
help
Support for remote processors (such as DSP coprocessors). These
are mainly used on embedded systems.
@@ -90,6 +91,7 @@ config QCOM_ADSP_PIL
depends on QCOM_SMEM
depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
select MFD_SYSCON
select QCOM_MDT_LOADER
select QCOM_RPROC_COMMON
@@ -107,6 +109,7 @@ config QCOM_Q6V5_PIL
depends on QCOM_SMEM
depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
select MFD_SYSCON
select QCOM_RPROC_COMMON
select QCOM_SCM
@@ -114,12 +117,28 @@ config QCOM_Q6V5_PIL
Say y here to support the Qualcomm Peripherial Image Loader for the
Hexagon V5 based remote processors.
+config QCOM_SYSMON
+ tristate "Qualcomm sysmon driver"
+ depends on RPMSG
+ depends on ARCH_QCOM
+ depends on NET
+ select QCOM_QMI_HELPERS
+ help
+ The sysmon driver implements a sysmon QMI client and a handler for
+ the sys_mon SMD and GLINK channel, which are used for graceful
+ shutdown, retrieving failure information and propagating information
+ about other subsystems being shut down.
+
+ Say y here if your system runs firmware on any other subsystems, e.g.
+ modem or DSP.
+
config QCOM_WCNSS_PIL
tristate "Qualcomm WCNSS Peripheral Image Loader"
depends on OF && ARCH_QCOM
depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
depends on QCOM_SMEM
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
select QCOM_MDT_LOADER
select QCOM_RPROC_COMMON
select QCOM_SCM
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 6e16450ce11f..02627ede8d4a 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_KEYSTONE_REMOTEPROC) += keystone_remoteproc.o
obj-$(CONFIG_QCOM_ADSP_PIL) += qcom_adsp_pil.o
obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o
obj-$(CONFIG_QCOM_Q6V5_PIL) += qcom_q6v5_pil.o
+obj-$(CONFIG_QCOM_SYSMON) += qcom_sysmon.o
obj-$(CONFIG_QCOM_WCNSS_PIL) += qcom_wcnss_pil.o
qcom_wcnss_pil-y += qcom_wcnss.o
qcom_wcnss_pil-y += qcom_wcnss_iris.o
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 633268e9d550..54c07fd3f204 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -333,14 +333,14 @@ static int imx_rproc_probe(struct platform_device *pdev)
/* set some other name then imx */
rproc = rproc_alloc(dev, "imx-rproc", &imx_rproc_ops,
NULL, sizeof(*priv));
- if (!rproc) {
- ret = -ENOMEM;
- goto err;
- }
+ if (!rproc)
+ return -ENOMEM;
dcfg = of_device_get_match_data(dev);
- if (!dcfg)
- return -EINVAL;
+ if (!dcfg) {
+ ret = -EINVAL;
+ goto err_put_rproc;
+ }
priv = rproc->priv;
priv->rproc = rproc;
@@ -359,8 +359,8 @@ static int imx_rproc_probe(struct platform_device *pdev)
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(dev, "Failed to get clock\n");
- rproc_free(rproc);
- return PTR_ERR(priv->clk);
+ ret = PTR_ERR(priv->clk);
+ goto err_put_rproc;
}
/*
@@ -370,8 +370,7 @@ static int imx_rproc_probe(struct platform_device *pdev)
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(&rproc->dev, "Failed to enable clock\n");
- rproc_free(rproc);
- return ret;
+ goto err_put_rproc;
}
ret = rproc_add(rproc);
@@ -380,13 +379,13 @@ static int imx_rproc_probe(struct platform_device *pdev)
goto err_put_clk;
}
- return ret;
+ return 0;
err_put_clk:
clk_disable_unprepare(priv->clk);
err_put_rproc:
rproc_free(rproc);
-err:
+
return ret;
}
diff --git a/drivers/remoteproc/qcom_adsp_pil.c b/drivers/remoteproc/qcom_adsp_pil.c
index 373c167892d7..89a86ce07f99 100644
--- a/drivers/remoteproc/qcom_adsp_pil.c
+++ b/drivers/remoteproc/qcom_adsp_pil.c
@@ -38,7 +38,10 @@ struct adsp_data {
const char *firmware_name;
int pas_id;
bool has_aggre2_clk;
+
const char *ssr_name;
+ const char *sysmon_name;
+ int ssctl_id;
};
struct qcom_adsp {
@@ -75,6 +78,7 @@ struct qcom_adsp {
struct qcom_rproc_glink glink_subdev;
struct qcom_rproc_subdev smd_subdev;
struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
};
static int adsp_load(struct rproc *rproc, const struct firmware *fw)
@@ -82,7 +86,9 @@ static int adsp_load(struct rproc *rproc, const struct firmware *fw)
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
return qcom_mdt_load(adsp->dev, fw, rproc->firmware, adsp->pas_id,
- adsp->mem_region, adsp->mem_phys, adsp->mem_size);
+ adsp->mem_region, adsp->mem_phys, adsp->mem_size,
+ &adsp->mem_reloc);
+
}
static int adsp_start(struct rproc *rproc)
@@ -177,6 +183,7 @@ static const struct rproc_ops adsp_ops = {
.start = adsp_start,
.stop = adsp_stop,
.da_to_va = adsp_da_to_va,
+ .parse_fw = qcom_register_dump_segments,
.load = adsp_load,
};
@@ -201,9 +208,6 @@ static irqreturn_t adsp_fatal_interrupt(int irq, void *dev)
rproc_report_crash(adsp->rproc, RPROC_FATAL_ERROR);
- if (!IS_ERR(msg))
- msg[0] = '\0';
-
return IRQ_HANDLED;
}
@@ -398,6 +402,9 @@ static int adsp_probe(struct platform_device *pdev)
qcom_add_glink_subdev(rproc, &adsp->glink_subdev);
qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
ret = rproc_add(rproc);
if (ret)
@@ -419,6 +426,7 @@ static int adsp_remove(struct platform_device *pdev)
rproc_del(adsp->rproc);
qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
rproc_free(adsp->rproc);
@@ -432,6 +440,8 @@ static const struct adsp_data adsp_resource_init = {
.pas_id = 1,
.has_aggre2_clk = false,
.ssr_name = "lpass",
+ .sysmon_name = "adsp",
+ .ssctl_id = 0x14,
};
static const struct adsp_data slpi_resource_init = {
@@ -440,6 +450,8 @@ static const struct adsp_data slpi_resource_init = {
.pas_id = 12,
.has_aggre2_clk = true,
.ssr_name = "dsps",
+ .sysmon_name = "slpi",
+ .ssctl_id = 0x16,
};
static const struct of_device_id adsp_of_match[] = {
diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
index 00602499713f..acfc99f82fb8 100644
--- a/drivers/remoteproc/qcom_common.c
+++ b/drivers/remoteproc/qcom_common.c
@@ -22,6 +22,7 @@
#include <linux/remoteproc.h>
#include <linux/rpmsg/qcom_glink.h>
#include <linux/rpmsg/qcom_smd.h>
+#include <linux/soc/qcom/mdt_loader.h>
#include "remoteproc_internal.h"
#include "qcom_common.h"
@@ -41,7 +42,7 @@ static int glink_subdev_probe(struct rproc_subdev *subdev)
return PTR_ERR_OR_ZERO(glink->edge);
}
-static void glink_subdev_remove(struct rproc_subdev *subdev)
+static void glink_subdev_remove(struct rproc_subdev *subdev, bool crashed)
{
struct qcom_rproc_glink *glink = to_glink_subdev(subdev);
@@ -74,11 +75,57 @@ EXPORT_SYMBOL_GPL(qcom_add_glink_subdev);
*/
void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink)
{
+ if (!glink->node)
+ return;
+
rproc_remove_subdev(rproc, &glink->subdev);
of_node_put(glink->node);
}
EXPORT_SYMBOL_GPL(qcom_remove_glink_subdev);
+/**
+ * qcom_register_dump_segments() - register segments for coredump
+ * @rproc: remoteproc handle
+ * @fw: firmware header
+ *
+ * Register all segments of the ELF in the remoteproc coredump segment list
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int qcom_register_dump_segments(struct rproc *rproc,
+ const struct firmware *fw)
+{
+ const struct elf32_phdr *phdrs;
+ const struct elf32_phdr *phdr;
+ const struct elf32_hdr *ehdr;
+ int ret;
+ int i;
+
+ ehdr = (struct elf32_hdr *)fw->data;
+ phdrs = (struct elf32_phdr *)(ehdr + 1);
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ phdr = &phdrs[i];
+
+ if (phdr->p_type != PT_LOAD)
+ continue;
+
+ if ((phdr->p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH)
+ continue;
+
+ if (!phdr->p_memsz)
+ continue;
+
+ ret = rproc_coredump_add_segment(rproc, phdr->p_paddr,
+ phdr->p_memsz);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_register_dump_segments);
+
static int smd_subdev_probe(struct rproc_subdev *subdev)
{
struct qcom_rproc_subdev *smd = to_smd_subdev(subdev);
@@ -88,7 +135,7 @@ static int smd_subdev_probe(struct rproc_subdev *subdev)
return PTR_ERR_OR_ZERO(smd->edge);
}
-static void smd_subdev_remove(struct rproc_subdev *subdev)
+static void smd_subdev_remove(struct rproc_subdev *subdev, bool crashed)
{
struct qcom_rproc_subdev *smd = to_smd_subdev(subdev);
@@ -121,6 +168,9 @@ EXPORT_SYMBOL_GPL(qcom_add_smd_subdev);
*/
void qcom_remove_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd)
{
+ if (!smd->node)
+ return;
+
rproc_remove_subdev(rproc, &smd->subdev);
of_node_put(smd->node);
}
@@ -157,7 +207,7 @@ static int ssr_notify_start(struct rproc_subdev *subdev)
return 0;
}
-static void ssr_notify_stop(struct rproc_subdev *subdev)
+static void ssr_notify_stop(struct rproc_subdev *subdev, bool crashed)
{
struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
index 728be9834d8b..58de71e4781c 100644
--- a/drivers/remoteproc/qcom_common.h
+++ b/drivers/remoteproc/qcom_common.h
@@ -4,6 +4,9 @@
#include <linux/remoteproc.h>
#include "remoteproc_internal.h"
+#include <linux/soc/qcom/qmi.h>
+
+struct qcom_sysmon;
struct qcom_rproc_glink {
struct rproc_subdev subdev;
@@ -30,6 +33,8 @@ struct qcom_rproc_ssr {
void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink);
void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink);
+int qcom_register_dump_segments(struct rproc *rproc, const struct firmware *fw);
+
void qcom_add_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd);
void qcom_remove_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd);
@@ -37,4 +42,22 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
const char *ssr_name);
void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+#if IS_ENABLED(CONFIG_QCOM_SYSMON)
+struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+ int ssctl_instance);
+void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon);
+#else
+static inline struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+ int ssctl_instance)
+{
+ return NULL;
+}
+
+static inline void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon)
+{
+}
+#endif
+
#endif
diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c
index b4e5e725848d..8e70a627e0bb 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -168,6 +168,7 @@ struct q6v5 {
struct qcom_rproc_subdev smd_subdev;
struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
bool need_mem_protection;
int mpss_perm;
int mba_perm;
@@ -939,9 +940,6 @@ static irqreturn_t q6v5_wdog_interrupt(int irq, void *dev)
rproc_report_crash(qproc->rproc, RPROC_WATCHDOG);
- if (!IS_ERR(msg))
- msg[0] = '\0';
-
return IRQ_HANDLED;
}
@@ -959,9 +957,6 @@ static irqreturn_t q6v5_fatal_interrupt(int irq, void *dev)
rproc_report_crash(qproc->rproc, RPROC_FATAL_ERROR);
- if (!IS_ERR(msg))
- msg[0] = '\0';
-
return IRQ_HANDLED;
}
@@ -1215,6 +1210,7 @@ static int q6v5_probe(struct platform_device *pdev)
qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
ret = rproc_add(rproc);
if (ret)
@@ -1234,6 +1230,7 @@ static int q6v5_remove(struct platform_device *pdev)
rproc_del(qproc->rproc);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
qcom_remove_smd_subdev(qproc->rproc, &qproc->smd_subdev);
qcom_remove_ssr_subdev(qproc->rproc, &qproc->ssr_subdev);
rproc_free(qproc->rproc);
diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c
new file mode 100644
index 000000000000..f085545d7da5
--- /dev/null
+++ b/drivers/remoteproc/qcom_sysmon.c
@@ -0,0 +1,579 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017, Linaro Ltd.
+ */
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/notifier.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/remoteproc/qcom_rproc.h>
+#include <linux/rpmsg.h>
+
+#include "qcom_common.h"
+
+static BLOCKING_NOTIFIER_HEAD(sysmon_notifiers);
+
+struct qcom_sysmon {
+ struct rproc_subdev subdev;
+ struct rproc *rproc;
+
+ struct list_head node;
+
+ const char *name;
+
+ int ssctl_version;
+ int ssctl_instance;
+
+ struct notifier_block nb;
+
+ struct device *dev;
+
+ struct rpmsg_endpoint *ept;
+ struct completion comp;
+ struct mutex lock;
+
+ bool ssr_ack;
+
+ struct qmi_handle qmi;
+ struct sockaddr_qrtr ssctl;
+};
+
+static DEFINE_MUTEX(sysmon_lock);
+static LIST_HEAD(sysmon_list);
+
+/**
+ * sysmon_send_event() - send notification of other remote's SSR event
+ * @sysmon: sysmon context
+ * @name: other remote's name
+ */
+static void sysmon_send_event(struct qcom_sysmon *sysmon, const char *name)
+{
+ char req[50];
+ int len;
+ int ret;
+
+ len = snprintf(req, sizeof(req), "ssr:%s:before_shutdown", name);
+ if (len >= sizeof(req))
+ return;
+
+ mutex_lock(&sysmon->lock);
+ reinit_completion(&sysmon->comp);
+ sysmon->ssr_ack = false;
+
+ ret = rpmsg_send(sysmon->ept, req, len);
+ if (ret < 0) {
+ dev_err(sysmon->dev, "failed to send sysmon event\n");
+ goto out_unlock;
+ }
+
+ ret = wait_for_completion_timeout(&sysmon->comp,
+ msecs_to_jiffies(5000));
+ if (!ret) {
+ dev_err(sysmon->dev, "timeout waiting for sysmon ack\n");
+ goto out_unlock;
+ }
+
+ if (!sysmon->ssr_ack)
+ dev_err(sysmon->dev, "unexpected response to sysmon event\n");
+
+out_unlock:
+ mutex_unlock(&sysmon->lock);
+}
+
+/**
+ * sysmon_request_shutdown() - request graceful shutdown of remote
+ * @sysmon: sysmon context
+ */
+static void sysmon_request_shutdown(struct qcom_sysmon *sysmon)
+{
+ char *req = "ssr:shutdown";
+ int ret;
+
+ mutex_lock(&sysmon->lock);
+ reinit_completion(&sysmon->comp);
+ sysmon->ssr_ack = false;
+
+ ret = rpmsg_send(sysmon->ept, req, strlen(req) + 1);
+ if (ret < 0) {
+ dev_err(sysmon->dev, "send sysmon shutdown request failed\n");
+ goto out_unlock;
+ }
+
+ ret = wait_for_completion_timeout(&sysmon->comp,
+ msecs_to_jiffies(5000));
+ if (!ret) {
+ dev_err(sysmon->dev, "timeout waiting for sysmon ack\n");
+ goto out_unlock;
+ }
+
+ if (!sysmon->ssr_ack)
+ dev_err(sysmon->dev,
+ "unexpected response to sysmon shutdown request\n");
+
+out_unlock:
+ mutex_unlock(&sysmon->lock);
+}
+
+static int sysmon_callback(struct rpmsg_device *rpdev, void *data, int count,
+ void *priv, u32 addr)
+{
+ struct qcom_sysmon *sysmon = priv;
+ const char *ssr_ack = "ssr:ack";
+ const int ssr_ack_len = strlen(ssr_ack) + 1;
+
+ if (!sysmon)
+ return -EINVAL;
+
+ if (count >= ssr_ack_len && !memcmp(data, ssr_ack, ssr_ack_len))
+ sysmon->ssr_ack = true;
+
+ complete(&sysmon->comp);
+
+ return 0;
+}
+
+#define SSCTL_SHUTDOWN_REQ 0x21
+#define SSCTL_SUBSYS_EVENT_REQ 0x23
+
+#define SSCTL_MAX_MSG_LEN 7
+
+#define SSCTL_SUBSYS_NAME_LENGTH 15
+
+enum {
+ SSCTL_SSR_EVENT_BEFORE_POWERUP,
+ SSCTL_SSR_EVENT_AFTER_POWERUP,
+ SSCTL_SSR_EVENT_BEFORE_SHUTDOWN,
+ SSCTL_SSR_EVENT_AFTER_SHUTDOWN,
+};
+
+enum {
+ SSCTL_SSR_EVENT_FORCED,
+ SSCTL_SSR_EVENT_GRACEFUL,
+};
+
+struct ssctl_shutdown_resp {
+ struct qmi_response_type_v01 resp;
+};
+
+static struct qmi_elem_info ssctl_shutdown_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct ssctl_shutdown_resp, resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {}
+};
+
+struct ssctl_subsys_event_req {
+ u8 subsys_name_len;
+ char subsys_name[SSCTL_SUBSYS_NAME_LENGTH];
+ u32 event;
+ u8 evt_driven_valid;
+ u32 evt_driven;
+};
+
+static struct qmi_elem_info ssctl_subsys_event_req_ei[] = {
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct ssctl_subsys_event_req,
+ subsys_name_len),
+ .ei_array = NULL,
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = SSCTL_SUBSYS_NAME_LENGTH,
+ .elem_size = sizeof(char),
+ .array_type = VAR_LEN_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct ssctl_subsys_event_req,
+ subsys_name),
+ .ei_array = NULL,
+ },
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct ssctl_subsys_event_req,
+ event),
+ .ei_array = NULL,
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct ssctl_subsys_event_req,
+ evt_driven_valid),
+ .ei_array = NULL,
+ },
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct ssctl_subsys_event_req,
+ evt_driven),
+ .ei_array = NULL,
+ },
+ {}
+};
+
+struct ssctl_subsys_event_resp {
+ struct qmi_response_type_v01 resp;
+};
+
+static struct qmi_elem_info ssctl_subsys_event_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct ssctl_subsys_event_resp,
+ resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {}
+};
+
+/**
+ * ssctl_request_shutdown() - request shutdown via SSCTL QMI service
+ * @sysmon: sysmon context
+ */
+static void ssctl_request_shutdown(struct qcom_sysmon *sysmon)
+{
+ struct ssctl_shutdown_resp resp;
+ struct qmi_txn txn;
+ int ret;
+
+ ret = qmi_txn_init(&sysmon->qmi, &txn, ssctl_shutdown_resp_ei, &resp);
+ if (ret < 0) {
+ dev_err(sysmon->dev, "failed to allocate QMI txn\n");
+ return;
+ }
+
+ ret = qmi_send_request(&sysmon->qmi, &sysmon->ssctl, &txn,
+ SSCTL_SHUTDOWN_REQ, 0, NULL, NULL);
+ if (ret < 0) {
+ dev_err(sysmon->dev, "failed to send shutdown request\n");
+ qmi_txn_cancel(&txn);
+ return;
+ }
+
+ ret = qmi_txn_wait(&txn, 5 * HZ);
+ if (ret < 0)
+ dev_err(sysmon->dev, "failed receiving QMI response\n");
+ else if (resp.resp.result)
+ dev_err(sysmon->dev, "shutdown request failed\n");
+ else
+ dev_dbg(sysmon->dev, "shutdown request completed\n");
+}
+
+/**
+ * ssctl_send_event() - send notification of other remote's SSR event
+ * @sysmon: sysmon context
+ * @name: other remote's name
+ */
+static void ssctl_send_event(struct qcom_sysmon *sysmon, const char *name)
+{
+ struct ssctl_subsys_event_resp resp;
+ struct ssctl_subsys_event_req req;
+ struct qmi_txn txn;
+ int ret;
+
+ memset(&resp, 0, sizeof(resp));
+ ret = qmi_txn_init(&sysmon->qmi, &txn, ssctl_subsys_event_resp_ei, &resp);
+ if (ret < 0) {
+ dev_err(sysmon->dev, "failed to allocate QMI txn\n");
+ return;
+ }
+
+ memset(&req, 0, sizeof(req));
+ strlcpy(req.subsys_name, name, sizeof(req.subsys_name));
+ req.subsys_name_len = strlen(req.subsys_name);
+ req.event = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN;
+ req.evt_driven_valid = true;
+ req.evt_driven = SSCTL_SSR_EVENT_FORCED;
+
+ ret = qmi_send_request(&sysmon->qmi, &sysmon->ssctl, &txn,
+ SSCTL_SUBSYS_EVENT_REQ, 40,
+ ssctl_subsys_event_req_ei, &req);
+ if (ret < 0) {
+ dev_err(sysmon->dev, "failed to send shutdown request\n");
+ qmi_txn_cancel(&txn);
+ return;
+ }
+
+ ret = qmi_txn_wait(&txn, 5 * HZ);
+ if (ret < 0)
+ dev_err(sysmon->dev, "failed receiving QMI response\n");
+ else if (resp.resp.result)
+ dev_err(sysmon->dev, "ssr event send failed\n");
+ else
+ dev_dbg(sysmon->dev, "ssr event send completed\n");
+}
+
+/**
+ * ssctl_new_server() - QMI callback indicating a new service
+ * @qmi: QMI handle
+ * @svc: service information
+ *
+ * Return: 0 if we're interested in this service, -EINVAL otherwise.
+ */
+static int ssctl_new_server(struct qmi_handle *qmi, struct qmi_service *svc)
+{
+ struct qcom_sysmon *sysmon = container_of(qmi, struct qcom_sysmon, qmi);
+
+ switch (svc->version) {
+ case 1:
+ if (svc->instance != 0)
+ return -EINVAL;
+ if (strcmp(sysmon->name, "modem"))
+ return -EINVAL;
+ break;
+ case 2:
+ if (svc->instance != sysmon->ssctl_instance)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ sysmon->ssctl_version = svc->version;
+
+ sysmon->ssctl.sq_family = AF_QIPCRTR;
+ sysmon->ssctl.sq_node = svc->node;
+ sysmon->ssctl.sq_port = svc->port;
+
+ svc->priv = sysmon;
+
+ return 0;
+}
+
+/**
+ * ssctl_del_server() - QMI callback indicating that @svc is removed
+ * @qmi: QMI handle
+ * @svc: service information
+ */
+static void ssctl_del_server(struct qmi_handle *qmi, struct qmi_service *svc)
+{
+ struct qcom_sysmon *sysmon = svc->priv;
+
+ sysmon->ssctl_version = 0;
+}
+
+static const struct qmi_ops ssctl_ops = {
+ .new_server = ssctl_new_server,
+ .del_server = ssctl_del_server,
+};
+
+static int sysmon_start(struct rproc_subdev *subdev)
+{
+ return 0;
+}
+
+static void sysmon_stop(struct rproc_subdev *subdev, bool crashed)
+{
+ struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon, subdev);
+
+ blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)sysmon->name);
+
+ /* Don't request graceful shutdown if we've crashed */
+ if (crashed)
+ return;
+
+ if (sysmon->ssctl_version)
+ ssctl_request_shutdown(sysmon);
+ else if (sysmon->ept)
+ sysmon_request_shutdown(sysmon);
+}
+
+/**
+ * sysmon_notify() - notify sysmon target of another's SSR
+ * @nb: notifier_block associated with sysmon instance
+ * @event: unused
+ * @data: SSR identifier of the remote that is going down
+ */
+static int sysmon_notify(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+ struct qcom_sysmon *sysmon = container_of(nb, struct qcom_sysmon, nb);
+ struct rproc *rproc = sysmon->rproc;
+ const char *ssr_name = data;
+
+ /* Skip non-running rprocs and the originating instance */
+ if (rproc->state != RPROC_RUNNING || !strcmp(data, sysmon->name)) {
+ dev_dbg(sysmon->dev, "not notifying %s\n", sysmon->name);
+ return NOTIFY_DONE;
+ }
+
+ /* Only SSCTL version 2 supports SSR events */
+ if (sysmon->ssctl_version == 2)
+ ssctl_send_event(sysmon, ssr_name);
+ else if (sysmon->ept)
+ sysmon_send_event(sysmon, ssr_name);
+
+ return NOTIFY_DONE;
+}
+
+/**
+ * qcom_add_sysmon_subdev() - create a sysmon subdev for the given remoteproc
+ * @rproc: rproc context to associate the subdev with
+ * @name: name of this subdev, to use in SSR
+ * @ssctl_instance: instance id of the ssctl QMI service
+ *
+ * Return: A new qcom_sysmon object, or NULL on failure
+ */
+struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+ int ssctl_instance)
+{
+ struct qcom_sysmon *sysmon;
+ int ret;
+
+ sysmon = kzalloc(sizeof(*sysmon), GFP_KERNEL);
+ if (!sysmon)
+ return NULL;
+
+ sysmon->dev = rproc->dev.parent;
+ sysmon->rproc = rproc;
+
+ sysmon->name = name;
+ sysmon->ssctl_instance = ssctl_instance;
+
+ init_completion(&sysmon->comp);
+ mutex_init(&sysmon->lock);
+
+ ret = qmi_handle_init(&sysmon->qmi, SSCTL_MAX_MSG_LEN, &ssctl_ops, NULL);
+ if (ret < 0) {
+ dev_err(sysmon->dev, "failed to initialize qmi handle\n");
+ kfree(sysmon);
+ return NULL;
+ }
+
+ qmi_add_lookup(&sysmon->qmi, 43, 0, 0);
+
+ rproc_add_subdev(rproc, &sysmon->subdev, sysmon_start, sysmon_stop);
+
+ sysmon->nb.notifier_call = sysmon_notify;
+ blocking_notifier_chain_register(&sysmon_notifiers, &sysmon->nb);
+
+ mutex_lock(&sysmon_lock);
+ list_add(&sysmon->node, &sysmon_list);
+ mutex_unlock(&sysmon_lock);
+
+ return sysmon;
+}
+EXPORT_SYMBOL_GPL(qcom_add_sysmon_subdev);
+
+/**
+ * qcom_remove_sysmon_subdev() - release a qcom_sysmon
+ * @sysmon: sysmon context, as retrieved by qcom_add_sysmon_subdev()
+ */
+void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon)
+{
+ if (!sysmon)
+ return;
+
+ mutex_lock(&sysmon_lock);
+ list_del(&sysmon->node);
+ mutex_unlock(&sysmon_lock);
+
+ blocking_notifier_chain_unregister(&sysmon_notifiers, &sysmon->nb);
+
+ rproc_remove_subdev(sysmon->rproc, &sysmon->subdev);
+
+ qmi_handle_release(&sysmon->qmi);
+
+ kfree(sysmon);
+}
+EXPORT_SYMBOL_GPL(qcom_remove_sysmon_subdev);
+
+/**
+ * sysmon_probe() - probe sys_mon channel
+ * @rpdev: rpmsg device handle
+ *
+ * Find the sysmon context associated with the ancestor remoteproc and assign
+ * this rpmsg device with said sysmon context.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+static int sysmon_probe(struct rpmsg_device *rpdev)
+{
+ struct qcom_sysmon *sysmon;
+ struct rproc *rproc;
+
+ rproc = rproc_get_by_child(&rpdev->dev);
+ if (!rproc) {
+ dev_err(&rpdev->dev, "sysmon device not child of rproc\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&sysmon_lock);
+ list_for_each_entry(sysmon, &sysmon_list, node) {
+ if (sysmon->rproc == rproc)
+ goto found;
+ }
+ mutex_unlock(&sysmon_lock);
+
+ dev_err(&rpdev->dev, "no sysmon associated with parent rproc\n");
+
+ return -EINVAL;
+
+found:
+ mutex_unlock(&sysmon_lock);
+
+ rpdev->ept->priv = sysmon;
+ sysmon->ept = rpdev->ept;
+
+ return 0;
+}
+
+/**
+ * sysmon_remove() - sys_mon channel remove handler
+ * @rpdev: rpmsg device handle
+ *
+ * Disassociate the rpmsg device with the sysmon instance.
+ */
+static void sysmon_remove(struct rpmsg_device *rpdev)
+{
+ struct qcom_sysmon *sysmon = rpdev->ept->priv;
+
+ sysmon->ept = NULL;
+}
+
+static const struct rpmsg_device_id sysmon_match[] = {
+ { "sys_mon" },
+ {}
+};
+
+static struct rpmsg_driver sysmon_driver = {
+ .probe = sysmon_probe,
+ .remove = sysmon_remove,
+ .callback = sysmon_callback,
+ .id_table = sysmon_match,
+ .drv = {
+ .name = "qcom_sysmon",
+ },
+};
+
+module_rpmsg_driver(sysmon_driver);
+
+MODULE_DESCRIPTION("Qualcomm sysmon driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index 3f0609236a76..b0e07e9f42d5 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -40,6 +40,7 @@
#define WCNSS_CRASH_REASON_SMEM 422
#define WCNSS_FIRMWARE_NAME "wcnss.mdt"
#define WCNSS_PAS_ID 6
+#define WCNSS_SSCTL_ID 0x13
#define WCNSS_SPARE_NVBIN_DLND BIT(25)
@@ -98,6 +99,7 @@ struct qcom_wcnss {
size_t mem_size;
struct qcom_rproc_subdev smd_subdev;
+ struct qcom_sysmon *sysmon;
};
static const struct wcnss_data riva_data = {
@@ -153,7 +155,8 @@ static int wcnss_load(struct rproc *rproc, const struct firmware *fw)
struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
return qcom_mdt_load(wcnss->dev, fw, rproc->firmware, WCNSS_PAS_ID,
- wcnss->mem_region, wcnss->mem_phys, wcnss->mem_size);
+ wcnss->mem_region, wcnss->mem_phys,
+ wcnss->mem_size, &wcnss->mem_reloc);
}
static void wcnss_indicate_nv_download(struct qcom_wcnss *wcnss)
@@ -308,6 +311,7 @@ static const struct rproc_ops wcnss_ops = {
.start = wcnss_start,
.stop = wcnss_stop,
.da_to_va = wcnss_da_to_va,
+ .parse_fw = qcom_register_dump_segments,
.load = wcnss_load,
};
@@ -332,9 +336,6 @@ static irqreturn_t wcnss_fatal_interrupt(int irq, void *dev)
rproc_report_crash(wcnss->rproc, RPROC_FATAL_ERROR);
- if (!IS_ERR(msg))
- msg[0] = '\0';
-
return IRQ_HANDLED;
}
@@ -551,6 +552,7 @@ static int wcnss_probe(struct platform_device *pdev)
}
qcom_add_smd_subdev(rproc, &wcnss->smd_subdev);
+ wcnss->sysmon = qcom_add_sysmon_subdev(rproc, "wcnss", WCNSS_SSCTL_ID);
ret = rproc_add(rproc);
if (ret)
@@ -573,6 +575,7 @@ static int wcnss_remove(struct platform_device *pdev)
qcom_smem_state_put(wcnss->state);
rproc_del(wcnss->rproc);
+ qcom_remove_sysmon_subdev(wcnss->sysmon);
qcom_remove_smd_subdev(wcnss->rproc, &wcnss->smd_subdev);
rproc_free(wcnss->rproc);
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 4170dfbd93bd..6d9c5832ce47 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -33,6 +33,7 @@
#include <linux/firmware.h>
#include <linux/string.h>
#include <linux/debugfs.h>
+#include <linux/devcoredump.h>
#include <linux/remoteproc.h>
#include <linux/iommu.h>
#include <linux/idr.h>
@@ -307,7 +308,7 @@ static int rproc_vdev_do_probe(struct rproc_subdev *subdev)
return rproc_add_virtio_dev(rvdev, rvdev->id);
}
-static void rproc_vdev_do_remove(struct rproc_subdev *subdev)
+static void rproc_vdev_do_remove(struct rproc_subdev *subdev, bool crashed)
{
struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
@@ -788,17 +789,31 @@ static int rproc_probe_subdevices(struct rproc *rproc)
unroll_registration:
list_for_each_entry_continue_reverse(subdev, &rproc->subdevs, node)
- subdev->remove(subdev);
+ subdev->remove(subdev, true);
return ret;
}
-static void rproc_remove_subdevices(struct rproc *rproc)
+static void rproc_remove_subdevices(struct rproc *rproc, bool crashed)
{
struct rproc_subdev *subdev;
list_for_each_entry_reverse(subdev, &rproc->subdevs, node)
- subdev->remove(subdev);
+ subdev->remove(subdev, crashed);
+}
+
+/**
+ * rproc_coredump_cleanup() - clean up dump_segments list
+ * @rproc: the remote processor handle
+ */
+static void rproc_coredump_cleanup(struct rproc *rproc)
+{
+ struct rproc_dump_segment *entry, *tmp;
+
+ list_for_each_entry_safe(entry, tmp, &rproc->dump_segments, node) {
+ list_del(&entry->node);
+ kfree(entry);
+ }
}
/**
@@ -848,6 +863,8 @@ static void rproc_resource_cleanup(struct rproc *rproc)
/* clean up remote vdev entries */
list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node)
kref_put(&rvdev->refcount, rproc_vdev_release);
+
+ rproc_coredump_cleanup(rproc);
}
static int rproc_start(struct rproc *rproc, const struct firmware *fw)
@@ -927,8 +944,8 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
rproc->bootaddr = rproc_get_boot_addr(rproc, fw);
- /* load resource table */
- ret = rproc_load_rsc_table(rproc, fw);
+ /* Load resource table, core dump segment list etc from the firmware */
+ ret = rproc_parse_fw(rproc, fw);
if (ret)
goto disable_iommu;
@@ -992,13 +1009,13 @@ static int rproc_trigger_auto_boot(struct rproc *rproc)
return ret;
}
-static int rproc_stop(struct rproc *rproc)
+static int rproc_stop(struct rproc *rproc, bool crashed)
{
struct device *dev = &rproc->dev;
int ret;
/* remove any subdevices for the remote processor */
- rproc_remove_subdevices(rproc);
+ rproc_remove_subdevices(rproc, crashed);
/* the installed resource table is no longer accessible */
rproc->table_ptr = rproc->cached_table;
@@ -1018,6 +1035,113 @@ static int rproc_stop(struct rproc *rproc)
}
/**
+ * rproc_coredump_add_segment() - add segment of device memory to coredump
+ * @rproc: handle of a remote processor
+ * @da: device address
+ * @size: size of segment
+ *
+ * Add device memory to the list of segments to be included in a coredump for
+ * the remoteproc.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size)
+{
+ struct rproc_dump_segment *segment;
+
+ segment = kzalloc(sizeof(*segment), GFP_KERNEL);
+ if (!segment)
+ return -ENOMEM;
+
+ segment->da = da;
+ segment->size = size;
+
+ list_add_tail(&segment->node, &rproc->dump_segments);
+
+ return 0;
+}
+EXPORT_SYMBOL(rproc_coredump_add_segment);
+
+/**
+ * rproc_coredump() - perform coredump
+ * @rproc: rproc handle
+ *
+ * This function will generate an ELF header for the registered segments
+ * and create a devcoredump device associated with rproc.
+ */
+static void rproc_coredump(struct rproc *rproc)
+{
+ struct rproc_dump_segment *segment;
+ struct elf32_phdr *phdr;
+ struct elf32_hdr *ehdr;
+ size_t data_size;
+ size_t offset;
+ void *data;
+ void *ptr;
+ int phnum = 0;
+
+ if (list_empty(&rproc->dump_segments))
+ return;
+
+ data_size = sizeof(*ehdr);
+ list_for_each_entry(segment, &rproc->dump_segments, node) {
+ data_size += sizeof(*phdr) + segment->size;
+
+ phnum++;
+ }
+
+ data = vmalloc(data_size);
+ if (!data)
+ return;
+
+ ehdr = data;
+
+ memset(ehdr, 0, sizeof(*ehdr));
+ memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
+ ehdr->e_ident[EI_CLASS] = ELFCLASS32;
+ ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
+ ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
+ ehdr->e_type = ET_CORE;
+ ehdr->e_machine = EM_NONE;
+ ehdr->e_version = EV_CURRENT;
+ ehdr->e_entry = rproc->bootaddr;
+ ehdr->e_phoff = sizeof(*ehdr);
+ ehdr->e_ehsize = sizeof(*ehdr);
+ ehdr->e_phentsize = sizeof(*phdr);
+ ehdr->e_phnum = phnum;
+
+ phdr = data + ehdr->e_phoff;
+ offset = ehdr->e_phoff + sizeof(*phdr) * ehdr->e_phnum;
+ list_for_each_entry(segment, &rproc->dump_segments, node) {
+ memset(phdr, 0, sizeof(*phdr));
+ phdr->p_type = PT_LOAD;
+ phdr->p_offset = offset;
+ phdr->p_vaddr = segment->da;
+ phdr->p_paddr = segment->da;
+ phdr->p_filesz = segment->size;
+ phdr->p_memsz = segment->size;
+ phdr->p_flags = PF_R | PF_W | PF_X;
+ phdr->p_align = 0;
+
+ ptr = rproc_da_to_va(rproc, segment->da, segment->size);
+ if (!ptr) {
+ dev_err(&rproc->dev,
+ "invalid coredump segment (%pad, %zu)\n",
+ &segment->da, segment->size);
+ memset(data + offset, 0xff, segment->size);
+ } else {
+ memcpy(data + offset, ptr, segment->size);
+ }
+
+ offset += phdr->p_filesz;
+ phdr++;
+ }
+
+ dev_coredumpv(&rproc->dev, data, data_size, GFP_KERNEL);
+}
+
+/**
* rproc_trigger_recovery() - recover a remoteproc
* @rproc: the remote processor
*
@@ -1039,10 +1163,13 @@ int rproc_trigger_recovery(struct rproc *rproc)
if (ret)
return ret;
- ret = rproc_stop(rproc);
+ ret = rproc_stop(rproc, false);
if (ret)
goto unlock_mutex;
+ /* generate coredump */
+ rproc_coredump(rproc);
+
/* load firmware */
ret = request_firmware(&firmware_p, rproc->firmware, dev);
if (ret < 0) {
@@ -1189,7 +1316,7 @@ void rproc_shutdown(struct rproc *rproc)
if (!atomic_dec_and_test(&rproc->power))
goto out;
- ret = rproc_stop(rproc);
+ ret = rproc_stop(rproc, true);
if (ret) {
atomic_inc(&rproc->power);
goto out;
@@ -1428,7 +1555,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
/* Default to ELF loader if no load function is specified */
if (!rproc->ops->load) {
rproc->ops->load = rproc_elf_load_segments;
- rproc->ops->load_rsc_table = rproc_elf_load_rsc_table;
+ rproc->ops->parse_fw = rproc_elf_load_rsc_table;
rproc->ops->find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table;
rproc->ops->sanity_check = rproc_elf_sanity_check;
rproc->ops->get_boot_addr = rproc_elf_get_boot_addr;
@@ -1443,6 +1570,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
INIT_LIST_HEAD(&rproc->traces);
INIT_LIST_HEAD(&rproc->rvdevs);
INIT_LIST_HEAD(&rproc->subdevs);
+ INIT_LIST_HEAD(&rproc->dump_segments);
INIT_WORK(&rproc->crash_handler, rproc_crash_handler_work);
@@ -1535,7 +1663,7 @@ EXPORT_SYMBOL(rproc_del);
void rproc_add_subdev(struct rproc *rproc,
struct rproc_subdev *subdev,
int (*probe)(struct rproc_subdev *subdev),
- void (*remove)(struct rproc_subdev *subdev))
+ void (*remove)(struct rproc_subdev *subdev, bool crashed))
{
subdev->probe = probe;
subdev->remove = remove;
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 55a2950c5cb7..7570beb035b5 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -88,11 +88,10 @@ int rproc_load_segments(struct rproc *rproc, const struct firmware *fw)
return -EINVAL;
}
-static inline int rproc_load_rsc_table(struct rproc *rproc,
- const struct firmware *fw)
+static inline int rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
{
- if (rproc->ops->load_rsc_table)
- return rproc->ops->load_rsc_table(rproc, fw);
+ if (rproc->ops->parse_fw)
+ return rproc->ops->parse_fw(rproc, fw);
return 0;
}
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c
index e0f31ed096a5..768ef542a841 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -113,7 +113,7 @@ struct qcom_glink {
spinlock_t rx_lock;
struct list_head rx_queue;
- struct mutex tx_lock;
+ spinlock_t tx_lock;
spinlock_t idr_lock;
struct idr lcids;
@@ -288,15 +288,14 @@ static int qcom_glink_tx(struct qcom_glink *glink,
const void *data, size_t dlen, bool wait)
{
unsigned int tlen = hlen + dlen;
- int ret;
+ unsigned long flags;
+ int ret = 0;
/* Reject packets that are too big */
if (tlen >= glink->tx_pipe->length)
return -EINVAL;
- ret = mutex_lock_interruptible(&glink->tx_lock);
- if (ret)
- return ret;
+ spin_lock_irqsave(&glink->tx_lock, flags);
while (qcom_glink_tx_avail(glink) < tlen) {
if (!wait) {
@@ -304,7 +303,12 @@ static int qcom_glink_tx(struct qcom_glink *glink,
goto out;
}
+ /* Wait without holding the tx_lock */
+ spin_unlock_irqrestore(&glink->tx_lock, flags);
+
usleep_range(10000, 15000);
+
+ spin_lock_irqsave(&glink->tx_lock, flags);
}
qcom_glink_tx_write(glink, hdr, hlen, data, dlen);
@@ -313,7 +317,7 @@ static int qcom_glink_tx(struct qcom_glink *glink,
mbox_client_txdone(glink->mbox_chan, 0);
out:
- mutex_unlock(&glink->tx_lock);
+ spin_unlock_irqrestore(&glink->tx_lock, flags);
return ret;
}
@@ -1567,7 +1571,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev,
glink->features = features;
glink->intentless = intentless;
- mutex_init(&glink->tx_lock);
+ spin_lock_init(&glink->tx_lock);
spin_lock_init(&glink->rx_lock);
INIT_LIST_HEAD(&glink->rx_queue);
INIT_WORK(&glink->rx_work, qcom_glink_work);
diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c
index 892f2b92a4d8..3fa9d43e2c87 100644
--- a/drivers/rpmsg/qcom_glink_smem.c
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -217,6 +217,7 @@ struct qcom_glink *qcom_glink_smem_register(struct device *parent,
ret = device_register(dev);
if (ret) {
pr_err("failed to register glink edge\n");
+ put_device(dev);
return ERR_PTR(ret);
}
@@ -299,7 +300,7 @@ struct qcom_glink *qcom_glink_smem_register(struct device *parent,
return glink;
err_put_dev:
- put_device(dev);
+ device_unregister(dev);
return ERR_PTR(ret);
}
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
index 92d0c6a7a837..5ce9bf7b897d 100644
--- a/drivers/rpmsg/qcom_smd.c
+++ b/drivers/rpmsg/qcom_smd.c
@@ -167,9 +167,9 @@ struct qcom_smd_endpoint {
struct qcom_smd_channel *qsch;
};
-#define to_smd_device(_rpdev) container_of(_rpdev, struct qcom_smd_device, rpdev)
+#define to_smd_device(r) container_of(r, struct qcom_smd_device, rpdev)
#define to_smd_edge(d) container_of(d, struct qcom_smd_edge, dev)
-#define to_smd_endpoint(ept) container_of(ept, struct qcom_smd_endpoint, ept)
+#define to_smd_endpoint(e) container_of(e, struct qcom_smd_endpoint, ept)
/**
* struct qcom_smd_channel - smd channel struct
@@ -205,7 +205,7 @@ struct qcom_smd_channel {
struct smd_channel_info_pair *info;
struct smd_channel_info_word_pair *info_word;
- struct mutex tx_lock;
+ spinlock_t tx_lock;
wait_queue_head_t fblockread_event;
void *tx_fifo;
@@ -729,6 +729,7 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
{
__le32 hdr[5] = { cpu_to_le32(len), };
int tlen = sizeof(hdr) + len;
+ unsigned long flags;
int ret;
/* Word aligned channels only accept word size aligned data */
@@ -739,9 +740,11 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
if (tlen >= channel->fifo_size)
return -EINVAL;
- ret = mutex_lock_interruptible(&channel->tx_lock);
- if (ret)
- return ret;
+ /* Highlight the fact that if we enter the loop below we might sleep */
+ if (wait)
+ might_sleep();
+
+ spin_lock_irqsave(&channel->tx_lock, flags);
while (qcom_smd_get_tx_avail(channel) < tlen &&
channel->state == SMD_CHANNEL_OPENED) {
@@ -753,7 +756,7 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 0);
/* Wait without holding the tx_lock */
- mutex_unlock(&channel->tx_lock);
+ spin_unlock_irqrestore(&channel->tx_lock, flags);
ret = wait_event_interruptible(channel->fblockread_event,
qcom_smd_get_tx_avail(channel) >= tlen ||
@@ -761,9 +764,7 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
if (ret)
return ret;
- ret = mutex_lock_interruptible(&channel->tx_lock);
- if (ret)
- return ret;
+ spin_lock_irqsave(&channel->tx_lock, flags);
SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
}
@@ -787,7 +788,7 @@ static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
qcom_smd_signal_channel(channel);
out_unlock:
- mutex_unlock(&channel->tx_lock);
+ spin_unlock_irqrestore(&channel->tx_lock, flags);
return ret;
}
@@ -996,8 +997,26 @@ static struct device_node *qcom_smd_match_channel(struct device_node *edge_node,
return NULL;
}
+static int qcom_smd_announce_create(struct rpmsg_device *rpdev)
+{
+ struct qcom_smd_endpoint *qept = to_smd_endpoint(rpdev->ept);
+ struct qcom_smd_channel *channel = qept->qsch;
+ unsigned long flags;
+ bool kick_state;
+
+ spin_lock_irqsave(&channel->recv_lock, flags);
+ kick_state = qcom_smd_channel_intr(channel);
+ spin_unlock_irqrestore(&channel->recv_lock, flags);
+
+ if (kick_state)
+ schedule_work(&channel->edge->state_work);
+
+ return 0;
+}
+
static const struct rpmsg_device_ops qcom_smd_device_ops = {
.create_ept = qcom_smd_create_ept,
+ .announce_create = qcom_smd_announce_create,
};
static const struct rpmsg_endpoint_ops qcom_smd_endpoint_ops = {
@@ -1090,7 +1109,7 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
if (!channel->name)
return ERR_PTR(-ENOMEM);
- mutex_init(&channel->tx_lock);
+ spin_lock_init(&channel->tx_lock);
spin_lock_init(&channel->recv_lock);
init_waitqueue_head(&channel->fblockread_event);
init_waitqueue_head(&channel->state_change_event);
@@ -1234,6 +1253,11 @@ static void qcom_channel_state_worker(struct work_struct *work)
if (channel->state != SMD_CHANNEL_CLOSED)
continue;
+ remote_state = GET_RX_CHANNEL_INFO(channel, state);
+ if (remote_state != SMD_CHANNEL_OPENING &&
+ remote_state != SMD_CHANNEL_OPENED)
+ continue;
+
if (channel->registered)
continue;
@@ -1408,6 +1432,7 @@ struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent,
ret = device_register(&edge->dev);
if (ret) {
pr_err("failed to register smd edge\n");
+ put_device(&edge->dev);
return ERR_PTR(ret);
}
@@ -1428,7 +1453,7 @@ struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent,
return edge;
unregister_dev:
- put_device(&edge->dev);
+ device_unregister(&edge->dev);
return ERR_PTR(ret);
}
EXPORT_SYMBOL(qcom_smd_register_edge);
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 5a081762afcc..920a02f0462c 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -442,7 +442,7 @@ static int rpmsg_dev_probe(struct device *dev)
goto out;
}
- if (rpdev->ops->announce_create)
+ if (ept && rpdev->ops->announce_create)
err = rpdev->ops->announce_create(rpdev);
out:
return err;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 319e3c8976d5..59e6dede3db3 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -407,6 +407,16 @@ config RTC_DRV_ISL12022
This driver can also be built as a module. If so, the module
will be called rtc-isl12022.
+config RTC_DRV_ISL12026
+ tristate "Intersil ISL12026"
+ depends on OF || COMPILE_TEST
+ help
+ If you say yes here you get support for the
+ Intersil ISL12026 RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-isl12026.
+
config RTC_DRV_X1205
tristate "Xicor/Intersil X1205"
help
@@ -1413,6 +1423,7 @@ config RTC_DRV_AT91RM9200
config RTC_DRV_AT91SAM9
tristate "AT91SAM9 RTT as RTC"
depends on ARCH_AT91 || COMPILE_TEST
+ depends on HAS_IOMEM
select MFD_SYSCON
help
Some AT91SAM9 SoCs provide an RTT (Real Time Timer) block which
@@ -1502,7 +1513,7 @@ config RTC_DRV_STARFIRE
config RTC_DRV_TX4939
tristate "TX4939 SoC"
- depends on SOC_TX4939
+ depends on SOC_TX4939 || COMPILE_TEST
help
Driver for the internal RTC (Realtime Clock) module found on
Toshiba TX4939 SoC.
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index ee0206becd9f..5ff2fc0c361a 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -75,6 +75,7 @@ obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o
obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o
obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o
obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
+obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o
obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 722d683e0b0f..d37588f08055 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -211,6 +211,73 @@ static int rtc_device_get_id(struct device *dev)
return id;
}
+static void rtc_device_get_offset(struct rtc_device *rtc)
+{
+ time64_t range_secs;
+ u32 start_year;
+ int ret;
+
+ /*
+ * If RTC driver did not implement the range of RTC hardware device,
+ * then we can not expand the RTC range by adding or subtracting one
+ * offset.
+ */
+ if (rtc->range_min == rtc->range_max)
+ return;
+
+ ret = device_property_read_u32(rtc->dev.parent, "start-year",
+ &start_year);
+ if (!ret) {
+ rtc->start_secs = mktime64(start_year, 1, 1, 0, 0, 0);
+ rtc->set_start_time = true;
+ }
+
+ /*
+ * If user did not implement the start time for RTC driver, then no
+ * need to expand the RTC range.
+ */
+ if (!rtc->set_start_time)
+ return;
+
+ range_secs = rtc->range_max - rtc->range_min + 1;
+
+ /*
+ * If the start_secs is larger than the maximum seconds (rtc->range_max)
+ * supported by RTC hardware or the maximum seconds of new expanded
+ * range (start_secs + rtc->range_max - rtc->range_min) is less than
+ * rtc->range_min, which means the minimum seconds (rtc->range_min) of
+ * RTC hardware will be mapped to start_secs by adding one offset, so
+ * the offset seconds calculation formula should be:
+ * rtc->offset_secs = rtc->start_secs - rtc->range_min;
+ *
+ * If the start_secs is larger than the minimum seconds (rtc->range_min)
+ * supported by RTC hardware, then there is one region is overlapped
+ * between the original RTC hardware range and the new expanded range,
+ * and this overlapped region do not need to be mapped into the new
+ * expanded range due to it is valid for RTC device. So the minimum
+ * seconds of RTC hardware (rtc->range_min) should be mapped to
+ * rtc->range_max + 1, then the offset seconds formula should be:
+ * rtc->offset_secs = rtc->range_max - rtc->range_min + 1;
+ *
+ * If the start_secs is less than the minimum seconds (rtc->range_min),
+ * which is similar to case 2. So the start_secs should be mapped to
+ * start_secs + rtc->range_max - rtc->range_min + 1, then the
+ * offset seconds formula should be:
+ * rtc->offset_secs = -(rtc->range_max - rtc->range_min + 1);
+ *
+ * Otherwise the offset seconds should be 0.
+ */
+ if (rtc->start_secs > rtc->range_max ||
+ rtc->start_secs + range_secs - 1 < rtc->range_min)
+ rtc->offset_secs = rtc->start_secs - rtc->range_min;
+ else if (rtc->start_secs > rtc->range_min)
+ rtc->offset_secs = range_secs;
+ else if (rtc->start_secs < rtc->range_min)
+ rtc->offset_secs = -range_secs;
+ else
+ rtc->offset_secs = 0;
+}
+
/**
* rtc_device_register - register w/ RTC class
* @dev: the device to register
@@ -247,6 +314,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
dev_set_name(&rtc->dev, "rtc%d", id);
+ rtc_device_get_offset(rtc);
+
/* Check to see if there is an ALARM already set in hw */
err = __rtc_read_alarm(rtc, &alrm);
@@ -293,8 +362,6 @@ EXPORT_SYMBOL_GPL(rtc_device_register);
*/
void rtc_device_unregister(struct rtc_device *rtc)
{
- rtc_nvmem_unregister(rtc);
-
mutex_lock(&rtc->ops_lock);
/*
* Remove innards of this RTC, then disable it, before
@@ -312,6 +379,7 @@ static void devm_rtc_device_release(struct device *dev, void *res)
{
struct rtc_device *rtc = *(struct rtc_device **)res;
+ rtc_nvmem_unregister(rtc);
rtc_device_unregister(rtc);
}
@@ -382,6 +450,8 @@ static void devm_rtc_release_device(struct device *dev, void *res)
{
struct rtc_device *rtc = *(struct rtc_device **)res;
+ rtc_nvmem_unregister(rtc);
+
if (rtc->registered)
rtc_device_unregister(rtc);
else
@@ -435,6 +505,7 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
return -EINVAL;
rtc->owner = owner;
+ rtc_device_get_offset(rtc);
/* Check to see if there is an ALARM already set in hw */
err = __rtc_read_alarm(rtc, &alrm);
@@ -453,8 +524,6 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
rtc_proc_add_device(rtc);
- rtc_nvmem_register(rtc);
-
rtc->registered = true;
dev_info(rtc->dev.parent, "registered as %s\n",
dev_name(&rtc->dev));
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
index e1cfa06810ef..e79f2a181ad2 100644
--- a/drivers/rtc/hctosys.c
+++ b/drivers/rtc/hctosys.c
@@ -49,6 +49,11 @@ static int __init rtc_hctosys(void)
tv64.tv_sec = rtc_tm_to_time64(&tm);
+#if BITS_PER_LONG == 32
+ if (tv64.tv_sec > INT_MAX)
+ goto err_read;
+#endif
+
err = do_settimeofday64(&tv64);
dev_info(rtc->dev.parent,
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 672b192f8153..7cbdc9228dd5 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -17,9 +17,73 @@
#include <linux/log2.h>
#include <linux/workqueue.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/rtc.h>
+
static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer);
static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer);
+static void rtc_add_offset(struct rtc_device *rtc, struct rtc_time *tm)
+{
+ time64_t secs;
+
+ if (!rtc->offset_secs)
+ return;
+
+ secs = rtc_tm_to_time64(tm);
+
+ /*
+ * Since the reading time values from RTC device are always in the RTC
+ * original valid range, but we need to skip the overlapped region
+ * between expanded range and original range, which is no need to add
+ * the offset.
+ */
+ if ((rtc->start_secs > rtc->range_min && secs >= rtc->start_secs) ||
+ (rtc->start_secs < rtc->range_min &&
+ secs <= (rtc->start_secs + rtc->range_max - rtc->range_min)))
+ return;
+
+ rtc_time64_to_tm(secs + rtc->offset_secs, tm);
+}
+
+static void rtc_subtract_offset(struct rtc_device *rtc, struct rtc_time *tm)
+{
+ time64_t secs;
+
+ if (!rtc->offset_secs)
+ return;
+
+ secs = rtc_tm_to_time64(tm);
+
+ /*
+ * If the setting time values are in the valid range of RTC hardware
+ * device, then no need to subtract the offset when setting time to RTC
+ * device. Otherwise we need to subtract the offset to make the time
+ * values are valid for RTC hardware device.
+ */
+ if (secs >= rtc->range_min && secs <= rtc->range_max)
+ return;
+
+ rtc_time64_to_tm(secs - rtc->offset_secs, tm);
+}
+
+static int rtc_valid_range(struct rtc_device *rtc, struct rtc_time *tm)
+{
+ if (rtc->range_min != rtc->range_max) {
+ time64_t time = rtc_tm_to_time64(tm);
+ time64_t range_min = rtc->set_start_time ? rtc->start_secs :
+ rtc->range_min;
+ time64_t range_max = rtc->set_start_time ?
+ (rtc->start_secs + rtc->range_max - rtc->range_min) :
+ rtc->range_max;
+
+ if (time < range_min || time > range_max)
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
{
int err;
@@ -36,6 +100,8 @@ static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
return err;
}
+ rtc_add_offset(rtc, tm);
+
err = rtc_valid_tm(tm);
if (err < 0)
dev_dbg(&rtc->dev, "read_time: rtc_time isn't valid\n");
@@ -53,6 +119,8 @@ int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
err = __rtc_read_time(rtc, tm);
mutex_unlock(&rtc->ops_lock);
+
+ trace_rtc_read_time(rtc_tm_to_time64(tm), err);
return err;
}
EXPORT_SYMBOL_GPL(rtc_read_time);
@@ -65,6 +133,12 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
if (err != 0)
return err;
+ err = rtc_valid_range(rtc, tm);
+ if (err)
+ return err;
+
+ rtc_subtract_offset(rtc, tm);
+
err = mutex_lock_interruptible(&rtc->ops_lock);
if (err)
return err;
@@ -87,6 +161,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
mutex_unlock(&rtc->ops_lock);
/* A timer might have just expired */
schedule_work(&rtc->irqwork);
+
+ trace_rtc_set_time(rtc_tm_to_time64(tm), err);
return err;
}
EXPORT_SYMBOL_GPL(rtc_set_time);
@@ -119,6 +195,8 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al
}
mutex_unlock(&rtc->ops_lock);
+
+ trace_rtc_read_alarm(rtc_tm_to_time64(&alarm->time), err);
return err;
}
@@ -316,6 +394,7 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
}
mutex_unlock(&rtc->ops_lock);
+ trace_rtc_read_alarm(rtc_tm_to_time64(&alarm->time), err);
return err;
}
EXPORT_SYMBOL_GPL(rtc_read_alarm);
@@ -329,6 +408,8 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
err = rtc_valid_tm(&alarm->time);
if (err)
return err;
+
+ rtc_subtract_offset(rtc, &alarm->time);
scheduled = rtc_tm_to_time64(&alarm->time);
/* Make sure we're not setting alarms in the past */
@@ -352,6 +433,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
else
err = rtc->ops->set_alarm(rtc->dev.parent, alarm);
+ trace_rtc_set_alarm(rtc_tm_to_time64(&alarm->time), err);
return err;
}
@@ -363,6 +445,10 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
if (err != 0)
return err;
+ err = rtc_valid_range(rtc, &alarm->time);
+ if (err)
+ return err;
+
err = mutex_lock_interruptible(&rtc->ops_lock);
if (err)
return err;
@@ -375,6 +461,8 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
mutex_unlock(&rtc->ops_lock);
+
+ rtc_add_offset(rtc, &alarm->time);
return err;
}
EXPORT_SYMBOL_GPL(rtc_set_alarm);
@@ -406,6 +494,7 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
rtc->aie_timer.enabled = 1;
timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node);
+ trace_rtc_timer_enqueue(&rtc->aie_timer);
}
mutex_unlock(&rtc->ops_lock);
return err;
@@ -435,6 +524,8 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled);
mutex_unlock(&rtc->ops_lock);
+
+ trace_rtc_alarm_irq_enable(enabled, err);
return err;
}
EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable);
@@ -709,6 +800,8 @@ retry:
rtc->pie_enabled = enabled;
}
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+
+ trace_rtc_irq_set_state(enabled, err);
return err;
}
EXPORT_SYMBOL_GPL(rtc_irq_set_state);
@@ -745,6 +838,8 @@ retry:
}
}
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+
+ trace_rtc_irq_set_freq(freq, err);
return err;
}
EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
@@ -779,6 +874,7 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
}
timerqueue_add(&rtc->timerqueue, &timer->node);
+ trace_rtc_timer_enqueue(timer);
if (!next || ktime_before(timer->node.expires, next->expires)) {
struct rtc_wkalrm alarm;
int err;
@@ -790,6 +886,7 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
schedule_work(&rtc->irqwork);
} else if (err) {
timerqueue_del(&rtc->timerqueue, &timer->node);
+ trace_rtc_timer_dequeue(timer);
timer->enabled = 0;
return err;
}
@@ -803,6 +900,7 @@ static void rtc_alarm_disable(struct rtc_device *rtc)
return;
rtc->ops->alarm_irq_enable(rtc->dev.parent, false);
+ trace_rtc_alarm_irq_enable(0, 0);
}
/**
@@ -821,6 +919,7 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
{
struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
timerqueue_del(&rtc->timerqueue, &timer->node);
+ trace_rtc_timer_dequeue(timer);
timer->enabled = 0;
if (next == &timer->node) {
struct rtc_wkalrm alarm;
@@ -871,16 +970,19 @@ again:
/* expire timer */
timer = container_of(next, struct rtc_timer, node);
timerqueue_del(&rtc->timerqueue, &timer->node);
+ trace_rtc_timer_dequeue(timer);
timer->enabled = 0;
if (timer->task.func)
timer->task.func(timer->task.private_data);
+ trace_rtc_timer_fired(timer);
/* Re-add/fwd periodic timers */
if (ktime_to_ns(timer->period)) {
timer->node.expires = ktime_add(timer->node.expires,
timer->period);
timer->enabled = 1;
timerqueue_add(&rtc->timerqueue, &timer->node);
+ trace_rtc_timer_enqueue(timer);
}
}
@@ -902,6 +1004,7 @@ reprogram:
timer = container_of(next, struct rtc_timer, node);
timerqueue_del(&rtc->timerqueue, &timer->node);
+ trace_rtc_timer_dequeue(timer);
timer->enabled = 0;
dev_err(&rtc->dev, "__rtc_set_alarm: err=%d\n", err);
goto again;
@@ -992,6 +1095,8 @@ int rtc_read_offset(struct rtc_device *rtc, long *offset)
mutex_lock(&rtc->ops_lock);
ret = rtc->ops->read_offset(rtc->dev.parent, offset);
mutex_unlock(&rtc->ops_lock);
+
+ trace_rtc_read_offset(*offset, ret);
return ret;
}
@@ -1025,5 +1130,7 @@ int rtc_set_offset(struct rtc_device *rtc, long offset)
mutex_lock(&rtc->ops_lock);
ret = rtc->ops->set_offset(rtc->dev.parent, offset);
mutex_unlock(&rtc->ops_lock);
+
+ trace_rtc_set_offset(offset, ret);
return ret;
}
diff --git a/drivers/rtc/nvmem.c b/drivers/rtc/nvmem.c
index 8567b4ed9ac6..17ec4c8d0fad 100644
--- a/drivers/rtc/nvmem.c
+++ b/drivers/rtc/nvmem.c
@@ -14,8 +14,6 @@
#include <linux/rtc.h>
#include <linux/sysfs.h>
-#include "rtc-core.h"
-
/*
* Deprecated ABI compatibility, this should be removed at some point
*/
@@ -46,7 +44,7 @@ rtc_nvram_write(struct file *filp, struct kobject *kobj,
return nvmem_device_write(rtc->nvmem, off, count, buf);
}
-static int rtc_nvram_register(struct rtc_device *rtc)
+static int rtc_nvram_register(struct rtc_device *rtc, size_t size)
{
int err;
@@ -64,7 +62,7 @@ static int rtc_nvram_register(struct rtc_device *rtc)
rtc->nvram->read = rtc_nvram_read;
rtc->nvram->write = rtc_nvram_write;
- rtc->nvram->size = rtc->nvmem_config->size;
+ rtc->nvram->size = size;
err = sysfs_create_bin_file(&rtc->dev.parent->kobj,
rtc->nvram);
@@ -84,21 +82,28 @@ static void rtc_nvram_unregister(struct rtc_device *rtc)
/*
* New ABI, uses nvmem
*/
-void rtc_nvmem_register(struct rtc_device *rtc)
+int rtc_nvmem_register(struct rtc_device *rtc,
+ struct nvmem_config *nvmem_config)
{
- if (!rtc->nvmem_config)
- return;
+ if (!IS_ERR_OR_NULL(rtc->nvmem))
+ return -EBUSY;
+
+ if (!nvmem_config)
+ return -ENODEV;
- rtc->nvmem_config->dev = &rtc->dev;
- rtc->nvmem_config->owner = rtc->owner;
- rtc->nvmem = nvmem_register(rtc->nvmem_config);
+ nvmem_config->dev = rtc->dev.parent;
+ nvmem_config->owner = rtc->owner;
+ rtc->nvmem = nvmem_register(nvmem_config);
if (IS_ERR_OR_NULL(rtc->nvmem))
- return;
+ return PTR_ERR(rtc->nvmem);
/* Register the old ABI */
if (rtc->nvram_old_abi)
- rtc_nvram_register(rtc);
+ rtc_nvram_register(rtc, nvmem_config->size);
+
+ return 0;
}
+EXPORT_SYMBOL_GPL(rtc_nvmem_register);
void rtc_nvmem_unregister(struct rtc_device *rtc)
{
diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c
index 466bf7f9a285..6cbafefa80a2 100644
--- a/drivers/rtc/rtc-88pm80x.c
+++ b/drivers/rtc/rtc-88pm80x.c
@@ -134,9 +134,9 @@ static int pm80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
struct pm80x_rtc_info *info = dev_get_drvdata(dev);
unsigned char buf[4];
unsigned long ticks, base, data;
- if ((tm->tm_year < 70) || (tm->tm_year > 138)) {
+ if (tm->tm_year > 206) {
dev_dbg(info->dev,
- "Set time %d out of range. Please set time between 1970 to 2038.\n",
+ "Set time %d out of range. Please set time between 1970 to 2106.\n",
1900 + tm->tm_year);
return -EINVAL;
}
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c
index 19e53b3b8e00..01ffc0ef8033 100644
--- a/drivers/rtc/rtc-88pm860x.c
+++ b/drivers/rtc/rtc-88pm860x.c
@@ -135,9 +135,9 @@ static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm)
unsigned char buf[4];
unsigned long ticks, base, data;
- if ((tm->tm_year < 70) || (tm->tm_year > 138)) {
+ if (tm->tm_year > 206) {
dev_dbg(info->dev, "Set time %d out of range. "
- "Please set time between 1970 to 2038.\n",
+ "Please set time between 1970 to 2106.\n",
1900 + tm->tm_year);
return -EINVAL;
}
diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c
index ef5c16dfabfa..8dc451932446 100644
--- a/drivers/rtc/rtc-ab-b5ze-s3.c
+++ b/drivers/rtc/rtc-ab-b5ze-s3.c
@@ -217,7 +217,7 @@ static int _abb5zes3_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct abb5zes3_rtc_data *data = dev_get_drvdata(dev);
u8 regs[ABB5ZES3_REG_RTC_SC + ABB5ZES3_RTC_SEC_LEN];
- int ret;
+ int ret = 0;
/*
* As we need to read CTRL1 register anyway to access 24/12h
@@ -255,8 +255,6 @@ static int _abb5zes3_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon = bcd2bin(regs[ABB5ZES3_REG_RTC_MO]) - 1; /* starts at 1 */
tm->tm_year = bcd2bin(regs[ABB5ZES3_REG_RTC_YR]) + 100;
- ret = rtc_valid_tm(tm);
-
err:
return ret;
}
diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c
index 9b725c553058..821ff52a2222 100644
--- a/drivers/rtc/rtc-ab3100.c
+++ b/drivers/rtc/rtc-ab3100.c
@@ -106,7 +106,7 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time64_to_tm(time, tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
index 24a0af650a1b..e28f4401fd35 100644
--- a/drivers/rtc/rtc-ab8500.c
+++ b/drivers/rtc/rtc-ab8500.c
@@ -36,10 +36,6 @@
#define AB8500_RTC_FORCE_BKUP_REG 0x0D
#define AB8500_RTC_CALIB_REG 0x0E
#define AB8500_RTC_SWITCH_STAT_REG 0x0F
-#define AB8540_RTC_ALRM_SEC 0x22
-#define AB8540_RTC_ALRM_MIN_LOW_REG 0x23
-#define AB8540_RTC_ALRM_MIN_MID_REG 0x24
-#define AB8540_RTC_ALRM_MIN_HI_REG 0x25
/* RtcReadRequest bits */
#define RTC_READ_REQUEST 0x01
@@ -63,11 +59,6 @@ static const u8 ab8500_rtc_alarm_regs[] = {
AB8500_RTC_ALRM_MIN_LOW_REG
};
-static const u8 ab8540_rtc_alarm_regs[] = {
- AB8540_RTC_ALRM_MIN_HI_REG, AB8540_RTC_ALRM_MIN_MID_REG,
- AB8540_RTC_ALRM_MIN_LOW_REG, AB8540_RTC_ALRM_SEC
-};
-
/* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */
static unsigned long get_elapsed_seconds(int year)
{
@@ -131,7 +122,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
secs += get_elapsed_seconds(AB8500_RTC_EPOCH);
rtc_time_to_tm(secs, tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -277,43 +268,6 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return ab8500_rtc_irq_enable(dev, alarm->enabled);
}
-static int ab8540_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
-{
- int retval, i;
- unsigned char buf[ARRAY_SIZE(ab8540_rtc_alarm_regs)];
- unsigned long mins, secs = 0;
-
- if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) {
- dev_dbg(dev, "year should be equal to or greater than %d\n",
- AB8500_RTC_EPOCH);
- return -EINVAL;
- }
-
- /* Get the number of seconds since 1970 */
- rtc_tm_to_time(&alarm->time, &secs);
-
- /*
- * Convert it to the number of seconds since 01-01-2000 00:00:00
- */
- secs -= get_elapsed_seconds(AB8500_RTC_EPOCH);
- mins = secs / 60;
-
- buf[3] = secs % 60;
- buf[2] = mins & 0xFF;
- buf[1] = (mins >> 8) & 0xFF;
- buf[0] = (mins >> 16) & 0xFF;
-
- /* Set the alarm time */
- for (i = 0; i < ARRAY_SIZE(ab8540_rtc_alarm_regs); i++) {
- retval = abx500_set_register_interruptible(dev, AB8500_RTC,
- ab8540_rtc_alarm_regs[i], buf[i]);
- if (retval < 0)
- return retval;
- }
-
- return ab8500_rtc_irq_enable(dev, alarm->enabled);
-}
-
static int ab8500_rtc_set_calibration(struct device *dev, int calibration)
{
int retval;
@@ -435,17 +389,8 @@ static const struct rtc_class_ops ab8500_rtc_ops = {
.alarm_irq_enable = ab8500_rtc_irq_enable,
};
-static const struct rtc_class_ops ab8540_rtc_ops = {
- .read_time = ab8500_rtc_read_time,
- .set_time = ab8500_rtc_set_time,
- .read_alarm = ab8500_rtc_read_alarm,
- .set_alarm = ab8540_rtc_set_alarm,
- .alarm_irq_enable = ab8500_rtc_irq_enable,
-};
-
static const struct platform_device_id ab85xx_rtc_ids[] = {
{ "ab8500-rtc", (kernel_ulong_t)&ab8500_rtc_ops, },
- { "ab8540-rtc", (kernel_ulong_t)&ab8540_rtc_ops, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, ab85xx_rtc_ids);
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index b033bc556f5d..2cefa67a1132 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -172,11 +172,7 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon = bcd2bin(buf[ABX8XX_REG_MO] & 0x1F) - 1;
tm->tm_year = bcd2bin(buf[ABX8XX_REG_YR]) + 100;
- err = rtc_valid_tm(tm);
- if (err < 0)
- dev_err(&client->dev, "retrieved date/time is not valid.\n");
-
- return err;
+ return 0;
}
static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c
index 8ff9dc3fe5bf..3fe576fdd45e 100644
--- a/drivers/rtc/rtc-ac100.c
+++ b/drivers/rtc/rtc-ac100.c
@@ -183,7 +183,29 @@ static int ac100_clkout_determine_rate(struct clk_hw *hw,
for (i = 0; i < num_parents; i++) {
struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
- unsigned long tmp, prate = clk_hw_get_rate(parent);
+ unsigned long tmp, prate;
+
+ /*
+ * The clock has two parents, one is a fixed clock which is
+ * internally registered by the ac100 driver. The other parent
+ * is a clock from the codec side of the chip, which we
+ * properly declare and reference in the devicetree and is
+ * not implemented in any driver right now.
+ * If the clock core looks for the parent of that second
+ * missing clock, it can't find one that is registered and
+ * returns NULL.
+ * So we end up in a situation where clk_hw_get_num_parents
+ * returns the amount of clocks we can be parented to, but
+ * clk_hw_get_parent_by_index will not return the orphan
+ * clocks.
+ * Thus we need to check if the parent exists before
+ * we get the parent rate, so we could use the RTC
+ * without waiting for the codec to be supported.
+ */
+ if (!parent)
+ continue;
+
+ prate = clk_hw_get_rate(parent);
tmp = ac100_clkout_round_rate(hw, req->rate, prate);
@@ -387,7 +409,7 @@ static int ac100_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_year = bcd2bin(reg[6] & AC100_RTC_YEA_MASK) +
AC100_YEAR_OFF;
- return rtc_valid_tm(rtc_tm);
+ return 0;
}
static int ac100_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 7418a763ce52..ee71e647fd43 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -349,6 +349,7 @@ static const struct rtc_class_ops at91_rtc_ops = {
};
static const struct regmap_config gpbr_regmap_config = {
+ .name = "gpbr",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c
index 2ba44ccb9c3a..7c5530c71285 100644
--- a/drivers/rtc/rtc-au1xxx.c
+++ b/drivers/rtc/rtc-au1xxx.c
@@ -36,7 +36,7 @@ static int au1xtoy_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time_to_tm(t, tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int au1xtoy_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c
index 98ac8d5c7901..ef52741000a8 100644
--- a/drivers/rtc/rtc-bq32k.c
+++ b/drivers/rtc/rtc-bq32k.c
@@ -36,6 +36,10 @@
#define BQ32K_CFG2 0x09 /* Trickle charger control */
#define BQ32K_TCFE BIT(6) /* Trickle charge FET bypass */
+#define MAX_LEN 10 /* Maximum number of consecutive
+ * register for this particular RTC.
+ */
+
struct bq32k_regs {
uint8_t seconds;
uint8_t minutes;
@@ -74,7 +78,7 @@ static int bq32k_read(struct device *dev, void *data, uint8_t off, uint8_t len)
static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len)
{
struct i2c_client *client = to_i2c_client(dev);
- uint8_t buffer[len + 1];
+ uint8_t buffer[MAX_LEN + 1];
buffer[0] = off;
memcpy(&buffer[1], data, len);
@@ -110,7 +114,7 @@ static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_year = bcd2bin(regs.years) +
((regs.cent_hours & BQ32K_CENT) ? 100 : 0);
- return rtc_valid_tm(tm);
+ return 0;
}
static int bq32k_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c
index 6cee61201c30..bdd6674a1054 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -60,6 +60,9 @@ static void brcmstb_waketmr_set_alarm(struct brcmstb_waketmr *timer,
{
brcmstb_waketmr_clear_alarm(timer);
+ /* Make sure we are actually counting in seconds */
+ writel_relaxed(timer->rate, timer->base + BRCMSTB_WKTMR_PRESCALER);
+
writel_relaxed(secs + 1, timer->base + BRCMSTB_WKTMR_ALARM);
}
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index f7c0f72abb56..1b3738a11702 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -541,11 +541,10 @@ static const struct rtc_class_ops cmos_rtc_ops = {
#define NVRAM_OFFSET (RTC_REG_D + 1)
-static ssize_t
-cmos_nvram_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t off, size_t count)
+static int cmos_nvram_read(void *priv, unsigned int off, void *val,
+ size_t count)
{
+ unsigned char *buf = val;
int retval;
off += NVRAM_OFFSET;
@@ -563,16 +562,13 @@ cmos_nvram_read(struct file *filp, struct kobject *kobj,
return retval;
}
-static ssize_t
-cmos_nvram_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t off, size_t count)
+static int cmos_nvram_write(void *priv, unsigned int off, void *val,
+ size_t count)
{
- struct cmos_rtc *cmos;
+ struct cmos_rtc *cmos = priv;
+ unsigned char *buf = val;
int retval;
- cmos = dev_get_drvdata(container_of(kobj, struct device, kobj));
-
/* NOTE: on at least PCs and Ataris, the boot firmware uses a
* checksum on part of the NVRAM data. That's currently ignored
* here. If userspace is smart enough to know what fields of
@@ -598,17 +594,6 @@ cmos_nvram_write(struct file *filp, struct kobject *kobj,
return retval;
}
-static struct bin_attribute nvram = {
- .attr = {
- .name = "nvram",
- .mode = S_IRUGO | S_IWUSR,
- },
-
- .read = cmos_nvram_read,
- .write = cmos_nvram_write,
- /* size gets set up later */
-};
-
/*----------------------------------------------------------------*/
static struct cmos_rtc cmos_rtc;
@@ -675,6 +660,14 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
unsigned char rtc_control;
unsigned address_space;
u32 flags = 0;
+ struct nvmem_config nvmem_cfg = {
+ .name = "cmos_nvram",
+ .word_size = 1,
+ .stride = 1,
+ .reg_read = cmos_nvram_read,
+ .reg_write = cmos_nvram_write,
+ .priv = &cmos_rtc,
+ };
/* there can be only one ... */
if (cmos_rtc.dev)
@@ -751,8 +744,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
cmos_rtc.dev = dev;
dev_set_drvdata(dev, &cmos_rtc);
- cmos_rtc.rtc = rtc_device_register(driver_name, dev,
- &cmos_rtc_ops, THIS_MODULE);
+ cmos_rtc.rtc = devm_rtc_allocate_device(dev);
if (IS_ERR(cmos_rtc.rtc)) {
retval = PTR_ERR(cmos_rtc.rtc);
goto cleanup0;
@@ -814,22 +806,25 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
}
}
- /* export at least the first block of NVRAM */
- nvram.size = address_space - NVRAM_OFFSET;
- retval = sysfs_create_bin_file(&dev->kobj, &nvram);
- if (retval < 0) {
- dev_dbg(dev, "can't create nvram file? %d\n", retval);
+ cmos_rtc.rtc->ops = &cmos_rtc_ops;
+ cmos_rtc.rtc->nvram_old_abi = true;
+ retval = rtc_register_device(cmos_rtc.rtc);
+ if (retval)
goto cleanup2;
- }
- dev_info(dev, "%s%s, %zd bytes nvram%s\n",
- !is_valid_irq(rtc_irq) ? "no alarms" :
- cmos_rtc.mon_alrm ? "alarms up to one year" :
- cmos_rtc.day_alrm ? "alarms up to one month" :
- "alarms up to one day",
- cmos_rtc.century ? ", y3k" : "",
- nvram.size,
- is_hpet_enabled() ? ", hpet irqs" : "");
+ /* export at least the first block of NVRAM */
+ nvmem_cfg.size = address_space - NVRAM_OFFSET;
+ if (rtc_nvmem_register(cmos_rtc.rtc, &nvmem_cfg))
+ dev_err(dev, "nvmem registration failed\n");
+
+ dev_info(dev, "%s%s, %d bytes nvram%s\n",
+ !is_valid_irq(rtc_irq) ? "no alarms" :
+ cmos_rtc.mon_alrm ? "alarms up to one year" :
+ cmos_rtc.day_alrm ? "alarms up to one month" :
+ "alarms up to one day",
+ cmos_rtc.century ? ", y3k" : "",
+ nvmem_cfg.size,
+ is_hpet_enabled() ? ", hpet irqs" : "");
return 0;
@@ -838,7 +833,6 @@ cleanup2:
free_irq(rtc_irq, cmos_rtc.rtc);
cleanup1:
cmos_rtc.dev = NULL;
- rtc_device_unregister(cmos_rtc.rtc);
cleanup0:
if (RTC_IOMAPPED)
release_region(ports->start, resource_size(ports));
@@ -862,14 +856,11 @@ static void cmos_do_remove(struct device *dev)
cmos_do_shutdown(cmos->irq);
- sysfs_remove_bin_file(&dev->kobj, &nvram);
-
if (is_valid_irq(cmos->irq)) {
free_irq(cmos->irq, cmos->rtc);
hpet_unregister_irq_handler(cmos_interrupt);
}
- rtc_device_unregister(cmos->rtc);
cmos->rtc = NULL;
ports = cmos->iomem;
@@ -1271,8 +1262,6 @@ MODULE_DEVICE_TABLE(of, of_cmos_match);
static __init void cmos_of_init(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
- struct rtc_time time;
- int ret;
const __be32 *val;
if (!node)
@@ -1285,16 +1274,6 @@ static __init void cmos_of_init(struct platform_device *pdev)
val = of_get_property(node, "freq-reg", NULL);
if (val)
CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT);
-
- cmos_read_time(&pdev->dev, &time);
- ret = rtc_valid_tm(&time);
- if (ret) {
- struct rtc_time def_time = {
- .tm_year = 1,
- .tm_mday = 1,
- };
- cmos_set_time(&pdev->dev, &def_time);
- }
}
#else
static inline void cmos_of_init(struct platform_device *pdev) {}
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c
index cfc4141d99cd..2fc517498a5d 100644
--- a/drivers/rtc/rtc-coh901331.c
+++ b/drivers/rtc/rtc-coh901331.c
@@ -82,7 +82,7 @@ static int coh901331_read_time(struct device *dev, struct rtc_time *tm)
if (readl(rtap->virtbase + COH901331_VALID)) {
rtc_time_to_tm(readl(rtap->virtbase + COH901331_CUR_TIME), tm);
clk_disable(rtap->clk);
- return rtc_valid_tm(tm);
+ return 0;
}
clk_disable(rtap->clk);
return -EINVAL;
diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h
index 513b9bedd2c8..0abf98983e13 100644
--- a/drivers/rtc/rtc-core.h
+++ b/drivers/rtc/rtc-core.h
@@ -46,11 +46,3 @@ static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
return NULL;
}
#endif
-
-#ifdef CONFIG_RTC_NVMEM
-void rtc_nvmem_register(struct rtc_device *rtc);
-void rtc_nvmem_unregister(struct rtc_device *rtc);
-#else
-static inline void rtc_nvmem_register(struct rtc_device *rtc) {}
-static inline void rtc_nvmem_unregister(struct rtc_device *rtc) {}
-#endif
diff --git a/drivers/rtc/rtc-cpcap.c b/drivers/rtc/rtc-cpcap.c
index 3a0333e1f21a..a8856f2b9bc2 100644
--- a/drivers/rtc/rtc-cpcap.c
+++ b/drivers/rtc/rtc-cpcap.c
@@ -119,7 +119,7 @@ static int cpcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
cpcap2rtc_time(tm, &cpcap_tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int cpcap_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c
index f0ea6899c731..bf7ced095c94 100644
--- a/drivers/rtc/rtc-cros-ec.c
+++ b/drivers/rtc/rtc-cros-ec.c
@@ -197,10 +197,10 @@ static int cros_ec_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
cros_ec_rtc->saved_alarm = (u32)alarm_time;
} else {
/* Don't set an alarm in the past. */
- if ((u32)alarm_time < current_time)
- alarm_offset = EC_RTC_ALARM_CLEAR;
- else
- alarm_offset = (u32)alarm_time - current_time;
+ if ((u32)alarm_time <= current_time)
+ return -ETIME;
+
+ alarm_offset = (u32)alarm_time - current_time;
}
ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM, alarm_offset);
diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c
index 4273377562ec..03044e1bc497 100644
--- a/drivers/rtc/rtc-da9052.c
+++ b/drivers/rtc/rtc-da9052.c
@@ -187,8 +187,7 @@ static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_min = v[0][1] & DA9052_RTC_MIN;
rtc_tm->tm_sec = v[0][0] & DA9052_RTC_SEC;
- ret = rtc_valid_tm(rtc_tm);
- return ret;
+ return 0;
}
idx = (1-idx);
diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c
index 678af8648c45..e08cd8130c23 100644
--- a/drivers/rtc/rtc-da9055.c
+++ b/drivers/rtc/rtc-da9055.c
@@ -158,7 +158,7 @@ static int da9055_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_min = v[1] & DA9055_RTC_MIN;
rtc_tm->tm_sec = v[0] & DA9055_RTC_SEC;
- return rtc_valid_tm(rtc_tm);
+ return 0;
}
static int da9055_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c
index f85cae240f12..b4e054c64bad 100644
--- a/drivers/rtc/rtc-da9063.c
+++ b/drivers/rtc/rtc-da9063.c
@@ -256,7 +256,7 @@ static int da9063_rtc_read_time(struct device *dev, struct rtc_time *tm)
else
rtc->rtc_sync = false;
- return rtc_valid_tm(tm);
+ return 0;
}
static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c
index 9c82b1da2d45..5f158715fb4c 100644
--- a/drivers/rtc/rtc-ds1216.c
+++ b/drivers/rtc/rtc-ds1216.c
@@ -99,7 +99,7 @@ static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
if (tm->tm_year < 70)
tm->tm_year += 100;
- return rtc_valid_tm(tm);
+ return 0;
}
static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c
index ef75c349dff9..0744916b79c5 100644
--- a/drivers/rtc/rtc-ds1286.c
+++ b/drivers/rtc/rtc-ds1286.c
@@ -211,7 +211,7 @@ static int ds1286_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon--;
- return rtc_valid_tm(tm);
+ return 0;
}
static int ds1286_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 0ec4be62322b..2a881150d51c 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -43,7 +43,7 @@ static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *time)
{
struct spi_device *spi = dev_get_drvdata(dev);
u8 buf[1 + RTC_CLCK_LEN];
- u8 *bp = buf;
+ u8 *bp;
int status;
/* Enable writing */
@@ -98,8 +98,7 @@ static int ds1302_rtc_get_time(struct device *dev, struct rtc_time *time)
time->tm_mon = bcd2bin(buf[RTC_ADDR_MON]) - 1;
time->tm_year = bcd2bin(buf[RTC_ADDR_YEAR]) + 100;
- /* Time may not be set */
- return rtc_valid_tm(time);
+ return 0;
}
static const struct rtc_class_ops ds1302_rtc_ops = {
@@ -112,7 +111,7 @@ static int ds1302_probe(struct spi_device *spi)
struct rtc_device *rtc;
u8 addr;
u8 buf[4];
- u8 *bp = buf;
+ u8 *bp;
int status;
/* Sanity check board setup data. This may be hooked up
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
index d8df2e9e14ad..2d502fc85698 100644
--- a/drivers/rtc/rtc-ds1305.c
+++ b/drivers/rtc/rtc-ds1305.c
@@ -203,8 +203,7 @@ static int ds1305_get_time(struct device *dev, struct rtc_time *time)
time->tm_hour, time->tm_mday,
time->tm_mon, time->tm_year, time->tm_wday);
- /* Time may not be set */
- return rtc_valid_tm(time);
+ return 0;
}
static int ds1305_set_time(struct device *dev, struct rtc_time *time)
@@ -544,15 +543,6 @@ static int ds1305_nvram_write(void *priv, unsigned int off, void *buf,
return spi_sync(spi, &m);
}
-static struct nvmem_config ds1305_nvmem_cfg = {
- .name = "ds1305_nvram",
- .word_size = 1,
- .stride = 1,
- .size = DS1305_NVRAM_LEN,
- .reg_read = ds1305_nvram_read,
- .reg_write = ds1305_nvram_write,
-};
-
/*----------------------------------------------------------------------*/
/*
@@ -566,6 +556,14 @@ static int ds1305_probe(struct spi_device *spi)
u8 addr, value;
struct ds1305_platform_data *pdata = dev_get_platdata(&spi->dev);
bool write_ctrl = false;
+ struct nvmem_config ds1305_nvmem_cfg = {
+ .name = "ds1305_nvram",
+ .word_size = 1,
+ .stride = 1,
+ .size = DS1305_NVRAM_LEN,
+ .reg_read = ds1305_nvram_read,
+ .reg_write = ds1305_nvram_write,
+ };
/* Sanity check board setup data. This may be hooked up
* in 3wire mode, but we don't care. Note that unless
@@ -703,15 +701,15 @@ static int ds1305_probe(struct spi_device *spi)
ds1305->rtc->ops = &ds1305_ops;
ds1305_nvmem_cfg.priv = ds1305;
- ds1305->rtc->nvmem_config = &ds1305_nvmem_cfg;
ds1305->rtc->nvram_old_abi = true;
-
status = rtc_register_device(ds1305->rtc);
if (status) {
dev_dbg(&spi->dev, "register rtc --> %d\n", status);
return status;
}
+ rtc_nvmem_register(ds1305->rtc, &ds1305_nvmem_cfg);
+
/* Maybe set up alarm IRQ; be ready to handle it triggering right
* away. NOTE that we don't share this. The signal is active low,
* and we can't ack it before a SPI message delay. We temporarily
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 923dde912f60..a13e59edff53 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -114,7 +114,6 @@ enum ds_type {
# define RX8025_BIT_XST 0x20
struct ds1307 {
- struct nvmem_config nvmem_cfg;
enum ds_type type;
unsigned long flags;
#define HAS_NVRAM 0 /* bit 0 == sysfs file active */
@@ -438,8 +437,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
t->tm_hour, t->tm_mday,
t->tm_mon, t->tm_year, t->tm_wday);
- /* initial clock setting can be undefined */
- return rtc_valid_tm(t);
+ return 0;
}
static int ds1307_set_time(struct device *dev, struct rtc_time *t)
@@ -1696,24 +1694,26 @@ read_rtc:
}
}
- if (chip->nvram_size) {
- ds1307->nvmem_cfg.name = "ds1307_nvram";
- ds1307->nvmem_cfg.word_size = 1;
- ds1307->nvmem_cfg.stride = 1;
- ds1307->nvmem_cfg.size = chip->nvram_size;
- ds1307->nvmem_cfg.reg_read = ds1307_nvram_read;
- ds1307->nvmem_cfg.reg_write = ds1307_nvram_write;
- ds1307->nvmem_cfg.priv = ds1307;
-
- ds1307->rtc->nvmem_config = &ds1307->nvmem_cfg;
- ds1307->rtc->nvram_old_abi = true;
- }
-
ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
err = rtc_register_device(ds1307->rtc);
if (err)
return err;
+ if (chip->nvram_size) {
+ struct nvmem_config nvmem_cfg = {
+ .name = "ds1307_nvram",
+ .word_size = 1,
+ .stride = 1,
+ .size = chip->nvram_size,
+ .reg_read = ds1307_nvram_read,
+ .reg_write = ds1307_nvram_write,
+ .priv = ds1307,
+ };
+
+ ds1307->rtc->nvram_old_abi = true;
+ rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
+ }
+
ds1307_hwmon_register(ds1307);
ds1307_clks_register(ds1307);
diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c
index 895fbeeb47fe..5208da4cf94a 100644
--- a/drivers/rtc/rtc-ds1343.c
+++ b/drivers/rtc/rtc-ds1343.c
@@ -153,120 +153,22 @@ static ssize_t ds1343_store_glitchfilter(struct device *dev,
static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter,
ds1343_store_glitchfilter);
-static ssize_t ds1343_nvram_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t off, size_t count)
+static int ds1343_nvram_write(void *priv, unsigned int off, void *val,
+ size_t bytes)
{
- int ret;
- unsigned char address;
- struct device *dev = kobj_to_dev(kobj);
- struct ds1343_priv *priv = dev_get_drvdata(dev);
-
- address = DS1343_NVRAM + off;
-
- ret = regmap_bulk_write(priv->map, address, buf, count);
- if (ret < 0)
- dev_err(&priv->spi->dev, "Error in nvram write %d", ret);
+ struct ds1343_priv *ds1343 = priv;
- return (ret < 0) ? ret : count;
+ return regmap_bulk_write(ds1343->map, DS1343_NVRAM + off, val, bytes);
}
-
-static ssize_t ds1343_nvram_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
- char *buf, loff_t off, size_t count)
+static int ds1343_nvram_read(void *priv, unsigned int off, void *val,
+ size_t bytes)
{
- int ret;
- unsigned char address;
- struct device *dev = kobj_to_dev(kobj);
- struct ds1343_priv *priv = dev_get_drvdata(dev);
+ struct ds1343_priv *ds1343 = priv;
- address = DS1343_NVRAM + off;
-
- ret = regmap_bulk_read(priv->map, address, buf, count);
- if (ret < 0)
- dev_err(&priv->spi->dev, "Error in nvram read %d\n", ret);
-
- return (ret < 0) ? ret : count;
+ return regmap_bulk_read(ds1343->map, DS1343_NVRAM + off, val, bytes);
}
-
-static struct bin_attribute nvram_attr = {
- .attr.name = "nvram",
- .attr.mode = S_IRUGO | S_IWUSR,
- .read = ds1343_nvram_read,
- .write = ds1343_nvram_write,
- .size = DS1343_NVRAM_LEN,
-};
-
-static ssize_t ds1343_show_alarmstatus(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ds1343_priv *priv = dev_get_drvdata(dev);
- int alarmstatus, data;
-
- regmap_read(priv->map, DS1343_CONTROL_REG, &data);
-
- alarmstatus = !!(data & DS1343_A0IE);
-
- if (alarmstatus)
- return sprintf(buf, "enabled\n");
- else
- return sprintf(buf, "disabled\n");
-}
-
-static DEVICE_ATTR(alarm_status, S_IRUGO, ds1343_show_alarmstatus, NULL);
-
-static ssize_t ds1343_show_alarmmode(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ds1343_priv *priv = dev_get_drvdata(dev);
- int alarm_mode, data;
- char *alarm_str;
-
- regmap_read(priv->map, DS1343_ALM0_SEC_REG, &data);
- alarm_mode = (data & 0x80) >> 4;
-
- regmap_read(priv->map, DS1343_ALM0_MIN_REG, &data);
- alarm_mode |= (data & 0x80) >> 5;
-
- regmap_read(priv->map, DS1343_ALM0_HOUR_REG, &data);
- alarm_mode |= (data & 0x80) >> 6;
-
- regmap_read(priv->map, DS1343_ALM0_DAY_REG, &data);
- alarm_mode |= (data & 0x80) >> 7;
-
- switch (alarm_mode) {
- case 15:
- alarm_str = "each second";
- break;
-
- case 7:
- alarm_str = "seconds match";
- break;
-
- case 3:
- alarm_str = "minutes and seconds match";
- break;
-
- case 1:
- alarm_str = "hours, minutes and seconds match";
- break;
-
- case 0:
- alarm_str = "day, hours, minutes and seconds match";
- break;
-
- default:
- alarm_str = "invalid";
- break;
- }
-
- return sprintf(buf, "%s\n", alarm_str);
-}
-
-static DEVICE_ATTR(alarm_mode, S_IRUGO, ds1343_show_alarmmode, NULL);
-
static ssize_t ds1343_show_tricklecharger(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -313,7 +215,6 @@ static DEVICE_ATTR(trickle_charger, S_IRUGO, ds1343_show_tricklecharger, NULL);
static int ds1343_sysfs_register(struct device *dev)
{
- struct ds1343_priv *priv = dev_get_drvdata(dev);
int err;
err = device_create_file(dev, &dev_attr_glitch_filter);
@@ -321,33 +222,9 @@ static int ds1343_sysfs_register(struct device *dev)
return err;
err = device_create_file(dev, &dev_attr_trickle_charger);
- if (err)
- goto error1;
-
- err = device_create_bin_file(dev, &nvram_attr);
- if (err)
- goto error2;
-
- if (priv->irq <= 0)
- return err;
-
- err = device_create_file(dev, &dev_attr_alarm_mode);
- if (err)
- goto error3;
-
- err = device_create_file(dev, &dev_attr_alarm_status);
if (!err)
- return err;
+ return 0;
- device_remove_file(dev, &dev_attr_alarm_mode);
-
-error3:
- device_remove_bin_file(dev, &nvram_attr);
-
-error2:
- device_remove_file(dev, &dev_attr_trickle_charger);
-
-error1:
device_remove_file(dev, &dev_attr_glitch_filter);
return err;
@@ -355,17 +232,8 @@ error1:
static void ds1343_sysfs_unregister(struct device *dev)
{
- struct ds1343_priv *priv = dev_get_drvdata(dev);
-
device_remove_file(dev, &dev_attr_glitch_filter);
device_remove_file(dev, &dev_attr_trickle_charger);
- device_remove_bin_file(dev, &nvram_attr);
-
- if (priv->irq <= 0)
- return;
-
- device_remove_file(dev, &dev_attr_alarm_status);
- device_remove_file(dev, &dev_attr_alarm_mode);
}
static int ds1343_read_time(struct device *dev, struct rtc_time *dt)
@@ -386,7 +254,7 @@ static int ds1343_read_time(struct device *dev, struct rtc_time *dt)
dt->tm_mon = bcd2bin(buf[5] & 0x1F) - 1;
dt->tm_year = bcd2bin(buf[6]) + 100; /* year offset from 1900 */
- return rtc_valid_tm(dt);
+ return 0;
}
static int ds1343_set_time(struct device *dev, struct rtc_time *dt)
@@ -599,14 +467,18 @@ static const struct rtc_class_ops ds1343_rtc_ops = {
static int ds1343_probe(struct spi_device *spi)
{
struct ds1343_priv *priv;
- struct regmap_config config;
+ struct regmap_config config = { .reg_bits = 8, .val_bits = 8,
+ .write_flag_mask = 0x80, };
unsigned int data;
int res;
-
- memset(&config, 0, sizeof(config));
- config.reg_bits = 8;
- config.val_bits = 8;
- config.write_flag_mask = 0x80;
+ struct nvmem_config nvmem_cfg = {
+ .name = "ds1343-",
+ .word_size = 1,
+ .stride = 1,
+ .size = DS1343_NVRAM_LEN,
+ .reg_read = ds1343_nvram_read,
+ .reg_write = ds1343_nvram_write,
+ };
priv = devm_kzalloc(&spi->dev, sizeof(struct ds1343_priv), GFP_KERNEL);
if (!priv)
@@ -646,12 +518,19 @@ static int ds1343_probe(struct spi_device *spi)
data &= ~(DS1343_OSF | DS1343_IRQF1 | DS1343_IRQF0);
regmap_write(priv->map, DS1343_STATUS_REG, data);
- priv->rtc = devm_rtc_device_register(&spi->dev, "ds1343",
- &ds1343_rtc_ops, THIS_MODULE);
- if (IS_ERR(priv->rtc)) {
- dev_err(&spi->dev, "unable to register rtc ds1343\n");
+ priv->rtc = devm_rtc_allocate_device(&spi->dev);
+ if (IS_ERR(priv->rtc))
return PTR_ERR(priv->rtc);
- }
+
+ priv->rtc->nvram_old_abi = true;
+ priv->rtc->ops = &ds1343_rtc_ops;
+
+ res = rtc_register_device(priv->rtc);
+ if (res)
+ return res;
+
+ nvmem_cfg.priv = priv;
+ rtc_nvmem_register(priv->rtc, &nvmem_cfg);
priv->irq = spi->irq;
diff --git a/drivers/rtc/rtc-ds1347.c b/drivers/rtc/rtc-ds1347.c
index ccfc9d43eb1e..938512c676ee 100644
--- a/drivers/rtc/rtc-ds1347.c
+++ b/drivers/rtc/rtc-ds1347.c
@@ -66,7 +66,7 @@ static int ds1347_read_time(struct device *dev, struct rtc_time *dt)
dt->tm_wday = bcd2bin(buf[5]) - 1;
dt->tm_year = bcd2bin(buf[6]) + 100;
- return rtc_valid_tm(dt);
+ return 0;
}
static int ds1347_set_time(struct device *dev, struct rtc_time *dt)
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c
index 4d5b007d7fc6..3b095401f848 100644
--- a/drivers/rtc/rtc-ds1390.c
+++ b/drivers/rtc/rtc-ds1390.c
@@ -153,7 +153,7 @@ static int ds1390_read_time(struct device *dev, struct rtc_time *dt)
/* adjust for century bit */
dt->tm_year = bcd2bin(chip->txrx_buf[6]) + ((chip->txrx_buf[5] & 0x80) ? 100 : 0);
- return rtc_valid_tm(dt);
+ return 0;
}
static int ds1390_set_time(struct device *dev, struct rtc_time *dt)
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index 1e95312a6f2e..a7d5ca428d68 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -277,10 +277,6 @@ static int ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_mon--;
- if (rtc_valid_tm(rtc_tm) < 0) {
- dev_err(dev, "retrieved date/time is not valid.\n");
- rtc_time_to_tm(0, rtc_tm);
- }
return 0;
}
@@ -422,20 +418,20 @@ static int ds1511_nvram_write(void *priv, unsigned int pos, void *buf,
return 0;
}
-static struct nvmem_config ds1511_nvmem_cfg = {
- .name = "ds1511_nvram",
- .word_size = 1,
- .stride = 1,
- .size = DS1511_RAM_MAX,
- .reg_read = ds1511_nvram_read,
- .reg_write = ds1511_nvram_write,
-};
-
static int ds1511_rtc_probe(struct platform_device *pdev)
{
struct resource *res;
struct rtc_plat_data *pdata;
int ret = 0;
+ struct nvmem_config ds1511_nvmem_cfg = {
+ .name = "ds1511_nvram",
+ .word_size = 1,
+ .stride = 1,
+ .size = DS1511_RAM_MAX,
+ .reg_read = ds1511_nvram_read,
+ .reg_write = ds1511_nvram_write,
+ .priv = &pdev->dev,
+ };
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -478,14 +474,14 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
pdata->rtc->ops = &ds1511_rtc_ops;
- ds1511_nvmem_cfg.priv = &pdev->dev;
- pdata->rtc->nvmem_config = &ds1511_nvmem_cfg;
pdata->rtc->nvram_old_abi = true;
ret = rtc_register_device(pdata->rtc);
if (ret)
return ret;
+ rtc_nvmem_register(pdata->rtc, &ds1511_nvmem_cfg);
+
/*
* if the platform has an interrupt in mind for this device,
* then by all means, set it
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 9961ec646fd2..2441b9a2b366 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -127,10 +127,6 @@ static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* year is 1900 + tm->tm_year */
tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
- if (rtc_valid_tm(tm) < 0) {
- dev_err(dev, "retrieved date/time is not valid.\n");
- rtc_time_to_tm(0, tm);
- }
return 0;
}
@@ -233,46 +229,32 @@ static const struct rtc_class_ops ds1553_rtc_ops = {
.alarm_irq_enable = ds1553_rtc_alarm_irq_enable,
};
-static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t size)
+static int ds1553_nvram_read(void *priv, unsigned int pos, void *val,
+ size_t bytes)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct platform_device *pdev = to_platform_device(dev);
+ struct platform_device *pdev = priv;
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
void __iomem *ioaddr = pdata->ioaddr;
- ssize_t count;
+ u8 *buf = val;
- for (count = 0; count < size; count++)
+ for (; bytes; bytes--)
*buf++ = readb(ioaddr + pos++);
- return count;
+ return 0;
}
-static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t size)
+static int ds1553_nvram_write(void *priv, unsigned int pos, void *val,
+ size_t bytes)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct platform_device *pdev = to_platform_device(dev);
+ struct platform_device *pdev = priv;
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
void __iomem *ioaddr = pdata->ioaddr;
- ssize_t count;
+ u8 *buf = val;
- for (count = 0; count < size; count++)
+ for (; bytes; bytes--)
writeb(*buf++, ioaddr + pos++);
- return count;
+ return 0;
}
-static struct bin_attribute ds1553_nvram_attr = {
- .attr = {
- .name = "nvram",
- .mode = S_IRUGO | S_IWUSR,
- },
- .size = RTC_OFFSET,
- .read = ds1553_nvram_read,
- .write = ds1553_nvram_write,
-};
-
static int ds1553_rtc_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -280,6 +262,15 @@ static int ds1553_rtc_probe(struct platform_device *pdev)
struct rtc_plat_data *pdata;
void __iomem *ioaddr;
int ret = 0;
+ struct nvmem_config nvmem_cfg = {
+ .name = "ds1553_nvram",
+ .word_size = 1,
+ .stride = 1,
+ .size = RTC_OFFSET,
+ .reg_read = ds1553_nvram_read,
+ .reg_write = ds1553_nvram_write,
+ .priv = pdev,
+ };
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -308,11 +299,17 @@ static int ds1553_rtc_probe(struct platform_device *pdev)
pdata->last_jiffies = jiffies;
platform_set_drvdata(pdev, pdata);
- pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
- &ds1553_rtc_ops, THIS_MODULE);
+ pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(pdata->rtc))
return PTR_ERR(pdata->rtc);
+ pdata->rtc->ops = &ds1553_rtc_ops;
+ pdata->rtc->nvram_old_abi = true;
+
+ ret = rtc_register_device(pdata->rtc);
+ if (ret)
+ return ret;
+
if (pdata->irq > 0) {
writeb(0, ioaddr + RTC_INTERRUPTS);
if (devm_request_irq(&pdev->dev, pdata->irq,
@@ -323,21 +320,9 @@ static int ds1553_rtc_probe(struct platform_device *pdev)
}
}
- ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
- if (ret)
- dev_err(&pdev->dev, "unable to create sysfs file: %s\n",
- ds1553_nvram_attr.attr.name);
-
- return 0;
-}
-
-static int ds1553_rtc_remove(struct platform_device *pdev)
-{
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ if (rtc_nvmem_register(pdata->rtc, &nvmem_cfg))
+ dev_err(&pdev->dev, "unable to register nvmem\n");
- sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
- if (pdata->irq > 0)
- writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
return 0;
}
@@ -346,7 +331,6 @@ MODULE_ALIAS("platform:rtc-ds1553");
static struct platform_driver ds1553_rtc_driver = {
.probe = ds1553_rtc_probe,
- .remove = ds1553_rtc_remove,
.driver = {
.name = "rtc-ds1553",
},
diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c
index ed43b4311660..1a39829d2b40 100644
--- a/drivers/rtc/rtc-ds1685.c
+++ b/drivers/rtc/rtc-ds1685.c
@@ -306,7 +306,7 @@ ds1685_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
tm->tm_isdst = 0; /* RTC has hardcoded timezone, so don't use. */
- return rtc_valid_tm(tm);
+ return 0;
}
/**
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 3abf1cbfb8ce..2d781180e968 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -53,9 +53,7 @@
struct rtc_plat_data {
void __iomem *ioaddr_nvram;
void __iomem *ioaddr_rtc;
- size_t size_nvram;
unsigned long last_jiffies;
- struct bin_attribute nvram_attr;
};
static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -114,7 +112,7 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* year is 1900 + tm->tm_year */
tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
- return rtc_valid_tm(tm);
+ return 0;
}
static const struct rtc_class_ops ds1742_rtc_ops = {
@@ -122,34 +120,28 @@ static const struct rtc_class_ops ds1742_rtc_ops = {
.set_time = ds1742_rtc_set_time,
};
-static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t size)
+static int ds1742_nvram_read(void *priv, unsigned int pos, void *val,
+ size_t bytes)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = priv;
void __iomem *ioaddr = pdata->ioaddr_nvram;
- ssize_t count;
+ u8 *buf = val;
- for (count = 0; count < size; count++)
+ for (; bytes; bytes--)
*buf++ = readb(ioaddr + pos++);
- return count;
+ return 0;
}
-static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t size)
+static int ds1742_nvram_write(void *priv, unsigned int pos, void *val,
+ size_t bytes)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = priv;
void __iomem *ioaddr = pdata->ioaddr_nvram;
- ssize_t count;
+ u8 *buf = val;
- for (count = 0; count < size; count++)
+ for (; bytes; bytes--)
writeb(*buf++, ioaddr + pos++);
- return count;
+ return 0;
}
static int ds1742_rtc_probe(struct platform_device *pdev)
@@ -160,6 +152,14 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
struct rtc_plat_data *pdata;
void __iomem *ioaddr;
int ret = 0;
+ struct nvmem_config nvmem_cfg = {
+ .name = "ds1742_nvram",
+ .word_size = 1,
+ .stride = 1,
+ .reg_read = ds1742_nvram_read,
+ .reg_write = ds1742_nvram_write,
+ };
+
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -171,15 +171,10 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
return PTR_ERR(ioaddr);
pdata->ioaddr_nvram = ioaddr;
- pdata->size_nvram = resource_size(res) - RTC_SIZE;
- pdata->ioaddr_rtc = ioaddr + pdata->size_nvram;
+ pdata->ioaddr_rtc = ioaddr + resource_size(res) - RTC_SIZE;
- sysfs_bin_attr_init(&pdata->nvram_attr);
- pdata->nvram_attr.attr.name = "nvram";
- pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR;
- pdata->nvram_attr.read = ds1742_nvram_read;
- pdata->nvram_attr.write = ds1742_nvram_write;
- pdata->nvram_attr.size = pdata->size_nvram;
+ nvmem_cfg.size = resource_size(res) - RTC_SIZE;
+ nvmem_cfg.priv = pdata;
/* turn RTC on if it was not on */
ioaddr = pdata->ioaddr_rtc;
@@ -196,24 +191,21 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
pdata->last_jiffies = jiffies;
platform_set_drvdata(pdev, pdata);
- rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
- &ds1742_rtc_ops, THIS_MODULE);
+
+ rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
- ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);
- if (ret)
- dev_err(&pdev->dev, "Unable to create sysfs entry: %s\n",
- pdata->nvram_attr.attr.name);
+ rtc->ops = &ds1742_rtc_ops;
+ rtc->nvram_old_abi = true;
- return 0;
-}
+ ret = rtc_register_device(rtc);
+ if (ret)
+ return ret;
-static int ds1742_rtc_remove(struct platform_device *pdev)
-{
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ if (rtc_nvmem_register(rtc, &nvmem_cfg))
+ dev_err(&pdev->dev, "Unable to register nvmem\n");
- sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);
return 0;
}
@@ -225,7 +217,6 @@ MODULE_DEVICE_TABLE(of, ds1742_rtc_of_match);
static struct platform_driver ds1742_rtc_driver = {
.probe = ds1742_rtc_probe,
- .remove = ds1742_rtc_remove,
.driver = {
.name = "rtc-ds1742",
.of_match_table = of_match_ptr(ds1742_rtc_of_match),
diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c
index 9a1582ed7070..b886b6a5c178 100644
--- a/drivers/rtc/rtc-ds2404.c
+++ b/drivers/rtc/rtc-ds2404.c
@@ -207,7 +207,7 @@ static int ds2404_read_time(struct device *dev, struct rtc_time *dt)
time = le32_to_cpu(time);
rtc_time_to_tm(time, dt);
- return rtc_valid_tm(dt);
+ return 0;
}
static int ds2404_set_mmss(struct device *dev, unsigned long secs)
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index 0550f7ba464f..7184e5145f12 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -145,7 +145,7 @@ static int ds3232_read_time(struct device *dev, struct rtc_time *time)
time->tm_year = bcd2bin(year) + add_century;
- return rtc_valid_tm(time);
+ return 0;
}
static int ds3232_set_time(struct device *dev, struct rtc_time *time)
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c
index 0130afd7fe88..3454e7814524 100644
--- a/drivers/rtc/rtc-efi.c
+++ b/drivers/rtc/rtc-efi.c
@@ -176,7 +176,7 @@ static int efi_read_time(struct device *dev, struct rtc_time *tm)
if (!convert_from_efi_time(&eft, tm))
return -EIO;
- return rtc_valid_tm(tm);
+ return 0;
}
static int efi_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c
index 576eadbba296..e1137670d4d2 100644
--- a/drivers/rtc/rtc-fm3130.c
+++ b/drivers/rtc/rtc-fm3130.c
@@ -136,8 +136,7 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t)
t->tm_hour, t->tm_mday,
t->tm_mon, t->tm_year, t->tm_wday);
- /* initial clock setting can be undefined */
- return rtc_valid_tm(t);
+ return 0;
}
diff --git a/drivers/rtc/rtc-goldfish.c b/drivers/rtc/rtc-goldfish.c
index d67769265185..a1c44d0c8557 100644
--- a/drivers/rtc/rtc-goldfish.c
+++ b/drivers/rtc/rtc-goldfish.c
@@ -235,3 +235,5 @@ static struct platform_driver goldfish_rtc = {
};
module_platform_driver(goldfish_rtc);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c
index 38586a024ee8..890ccfc9e5aa 100644
--- a/drivers/rtc/rtc-isl12022.c
+++ b/drivers/rtc/rtc-isl12022.c
@@ -104,8 +104,9 @@ static int isl12022_write_reg(struct i2c_client *client,
* In the routines that deal directly with the isl12022 hardware, we use
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
*/
-static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
uint8_t buf[ISL12022_REG_INT + 1];
int ret;
@@ -149,11 +150,12 @@ static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- return rtc_valid_tm(tm);
+ return 0;
}
-static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct isl12022 *isl12022 = i2c_get_clientdata(client);
size_t i;
int ret;
@@ -199,7 +201,7 @@ static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return ret;
}
- isl12022->write_enabled = 1;
+ isl12022->write_enabled = true;
}
/* hours, minutes and seconds */
@@ -228,16 +230,6 @@ static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return 0;
}
-static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
- return isl12022_get_datetime(to_i2c_client(dev), tm);
-}
-
-static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- return isl12022_set_datetime(to_i2c_client(dev), tm);
-}
-
static const struct rtc_class_ops isl12022_rtc_ops = {
.read_time = isl12022_rtc_read_time,
.set_time = isl12022_rtc_set_time,
diff --git a/drivers/rtc/rtc-isl12026.c b/drivers/rtc/rtc-isl12026.c
new file mode 100644
index 000000000000..97f594f9667c
--- /dev/null
+++ b/drivers/rtc/rtc-isl12026.c
@@ -0,0 +1,501 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * An I2C driver for the Intersil ISL 12026
+ *
+ * Copyright (c) 2018 Cavium, Inc.
+ */
+#include <linux/bcd.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+
+/* register offsets */
+#define ISL12026_REG_PWR 0x14
+# define ISL12026_REG_PWR_BSW BIT(6)
+# define ISL12026_REG_PWR_SBIB BIT(7)
+#define ISL12026_REG_SC 0x30
+#define ISL12026_REG_HR 0x32
+# define ISL12026_REG_HR_MIL BIT(7) /* military or 24 hour time */
+#define ISL12026_REG_SR 0x3f
+# define ISL12026_REG_SR_RTCF BIT(0)
+# define ISL12026_REG_SR_WEL BIT(1)
+# define ISL12026_REG_SR_RWEL BIT(2)
+# define ISL12026_REG_SR_MBZ BIT(3)
+# define ISL12026_REG_SR_OSCF BIT(4)
+
+/* The EEPROM array responds at i2c address 0x57 */
+#define ISL12026_EEPROM_ADDR 0x57
+
+#define ISL12026_PAGESIZE 16
+#define ISL12026_NVMEM_WRITE_TIME 20
+
+struct isl12026 {
+ struct rtc_device *rtc;
+ struct i2c_client *nvm_client;
+};
+
+static int isl12026_read_reg(struct i2c_client *client, int reg)
+{
+ u8 addr[] = {0, reg};
+ u8 val;
+ int ret;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = sizeof(addr),
+ .buf = addr
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &val
+ }
+ };
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret != ARRAY_SIZE(msgs)) {
+ dev_err(&client->dev, "read reg error, ret=%d\n", ret);
+ ret = ret < 0 ? ret : -EIO;
+ } else {
+ ret = val;
+ }
+
+ return ret;
+}
+
+static int isl12026_arm_write(struct i2c_client *client)
+{
+ int ret;
+ u8 op[3];
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = op
+ };
+
+ /* Set SR.WEL */
+ op[0] = 0;
+ op[1] = ISL12026_REG_SR;
+ op[2] = ISL12026_REG_SR_WEL;
+ msg.len = 3;
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret != 1) {
+ dev_err(&client->dev, "write error SR.WEL, ret=%d\n", ret);
+ ret = ret < 0 ? ret : -EIO;
+ goto out;
+ }
+
+ /* Set SR.WEL and SR.RWEL */
+ op[2] = ISL12026_REG_SR_WEL | ISL12026_REG_SR_RWEL;
+ msg.len = 3;
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret != 1) {
+ dev_err(&client->dev,
+ "write error SR.WEL|SR.RWEL, ret=%d\n", ret);
+ ret = ret < 0 ? ret : -EIO;
+ goto out;
+ } else {
+ ret = 0;
+ }
+out:
+ return ret;
+}
+
+static int isl12026_disarm_write(struct i2c_client *client)
+{
+ int ret;
+ u8 op[3] = {0, ISL12026_REG_SR, 0};
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .flags = 0,
+ .len = sizeof(op),
+ .buf = op
+ };
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret != 1) {
+ dev_err(&client->dev,
+ "write error SR, ret=%d\n", ret);
+ ret = ret < 0 ? ret : -EIO;
+ } else {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static int isl12026_write_reg(struct i2c_client *client, int reg, u8 val)
+{
+ int ret;
+ u8 op[3] = {0, reg, val};
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .flags = 0,
+ .len = sizeof(op),
+ .buf = op
+ };
+
+ ret = isl12026_arm_write(client);
+ if (ret)
+ return ret;
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret != 1) {
+ dev_err(&client->dev, "write error CCR, ret=%d\n", ret);
+ ret = ret < 0 ? ret : -EIO;
+ goto out;
+ }
+
+ msleep(ISL12026_NVMEM_WRITE_TIME);
+
+ ret = isl12026_disarm_write(client);
+out:
+ return ret;
+}
+
+static int isl12026_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int ret;
+ u8 op[10];
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .flags = 0,
+ .len = sizeof(op),
+ .buf = op
+ };
+
+ ret = isl12026_arm_write(client);
+ if (ret)
+ return ret;
+
+ /* Set the CCR registers */
+ op[0] = 0;
+ op[1] = ISL12026_REG_SC;
+ op[2] = bin2bcd(tm->tm_sec); /* SC */
+ op[3] = bin2bcd(tm->tm_min); /* MN */
+ op[4] = bin2bcd(tm->tm_hour) | ISL12026_REG_HR_MIL; /* HR */
+ op[5] = bin2bcd(tm->tm_mday); /* DT */
+ op[6] = bin2bcd(tm->tm_mon + 1); /* MO */
+ op[7] = bin2bcd(tm->tm_year % 100); /* YR */
+ op[8] = bin2bcd(tm->tm_wday & 7); /* DW */
+ op[9] = bin2bcd(tm->tm_year >= 100 ? 20 : 19); /* Y2K */
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret != 1) {
+ dev_err(&client->dev, "write error CCR, ret=%d\n", ret);
+ ret = ret < 0 ? ret : -EIO;
+ goto out;
+ }
+
+ ret = isl12026_disarm_write(client);
+out:
+ return ret;
+}
+
+static int isl12026_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ u8 ccr[8];
+ u8 addr[2];
+ u8 sr;
+ int ret;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = sizeof(addr),
+ .buf = addr
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ }
+ };
+
+ /* First, read SR */
+ addr[0] = 0;
+ addr[1] = ISL12026_REG_SR;
+ msgs[1].len = 1;
+ msgs[1].buf = &sr;
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret != ARRAY_SIZE(msgs)) {
+ dev_err(&client->dev, "read error, ret=%d\n", ret);
+ ret = ret < 0 ? ret : -EIO;
+ goto out;
+ }
+
+ if (sr & ISL12026_REG_SR_RTCF)
+ dev_warn(&client->dev, "Real-Time Clock Failure on read\n");
+ if (sr & ISL12026_REG_SR_OSCF)
+ dev_warn(&client->dev, "Oscillator Failure on read\n");
+
+ /* Second, CCR regs */
+ addr[0] = 0;
+ addr[1] = ISL12026_REG_SC;
+ msgs[1].len = sizeof(ccr);
+ msgs[1].buf = ccr;
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret != ARRAY_SIZE(msgs)) {
+ dev_err(&client->dev, "read error, ret=%d\n", ret);
+ ret = ret < 0 ? ret : -EIO;
+ goto out;
+ }
+
+ tm->tm_sec = bcd2bin(ccr[0] & 0x7F);
+ tm->tm_min = bcd2bin(ccr[1] & 0x7F);
+ if (ccr[2] & ISL12026_REG_HR_MIL)
+ tm->tm_hour = bcd2bin(ccr[2] & 0x3F);
+ else
+ tm->tm_hour = bcd2bin(ccr[2] & 0x1F) +
+ ((ccr[2] & 0x20) ? 12 : 0);
+ tm->tm_mday = bcd2bin(ccr[3] & 0x3F);
+ tm->tm_mon = bcd2bin(ccr[4] & 0x1F) - 1;
+ tm->tm_year = bcd2bin(ccr[5]);
+ if (bcd2bin(ccr[7]) == 20)
+ tm->tm_year += 100;
+ tm->tm_wday = ccr[6] & 0x07;
+
+ ret = 0;
+out:
+ return ret;
+}
+
+static const struct rtc_class_ops isl12026_rtc_ops = {
+ .read_time = isl12026_rtc_read_time,
+ .set_time = isl12026_rtc_set_time,
+};
+
+static int isl12026_nvm_read(void *p, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct isl12026 *priv = p;
+ int ret;
+ u8 addr[2];
+ struct i2c_msg msgs[] = {
+ {
+ .addr = priv->nvm_client->addr,
+ .flags = 0,
+ .len = sizeof(addr),
+ .buf = addr
+ }, {
+ .addr = priv->nvm_client->addr,
+ .flags = I2C_M_RD,
+ .buf = val
+ }
+ };
+
+ /*
+ * offset and bytes checked and limited by nvmem core, so
+ * proceed without further checks.
+ */
+ ret = mutex_lock_interruptible(&priv->rtc->ops_lock);
+ if (ret)
+ return ret;
+
+ /* 2 bytes of address, most significant first */
+ addr[0] = offset >> 8;
+ addr[1] = offset;
+ msgs[1].len = bytes;
+ ret = i2c_transfer(priv->nvm_client->adapter, msgs, ARRAY_SIZE(msgs));
+
+ mutex_unlock(&priv->rtc->ops_lock);
+
+ if (ret != ARRAY_SIZE(msgs)) {
+ dev_err(&priv->nvm_client->dev,
+ "nvmem read error, ret=%d\n", ret);
+ return ret < 0 ? ret : -EIO;
+ }
+
+ return 0;
+}
+
+static int isl12026_nvm_write(void *p, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct isl12026 *priv = p;
+ int ret;
+ u8 *v = val;
+ size_t chunk_size, num_written;
+ u8 payload[ISL12026_PAGESIZE + 2]; /* page + 2 address bytes */
+ struct i2c_msg msgs[] = {
+ {
+ .addr = priv->nvm_client->addr,
+ .flags = 0,
+ .buf = payload
+ }
+ };
+
+ /*
+ * offset and bytes checked and limited by nvmem core, so
+ * proceed without further checks.
+ */
+ ret = mutex_lock_interruptible(&priv->rtc->ops_lock);
+ if (ret)
+ return ret;
+
+ num_written = 0;
+ while (bytes) {
+ chunk_size = round_down(offset, ISL12026_PAGESIZE) +
+ ISL12026_PAGESIZE - offset;
+ chunk_size = min(bytes, chunk_size);
+ /*
+ * 2 bytes of address, most significant first, followed
+ * by page data bytes
+ */
+ memcpy(payload + 2, v + num_written, chunk_size);
+ payload[0] = offset >> 8;
+ payload[1] = offset;
+ msgs[0].len = chunk_size + 2;
+ ret = i2c_transfer(priv->nvm_client->adapter,
+ msgs, ARRAY_SIZE(msgs));
+ if (ret != ARRAY_SIZE(msgs)) {
+ dev_err(&priv->nvm_client->dev,
+ "nvmem write error, ret=%d\n", ret);
+ ret = ret < 0 ? ret : -EIO;
+ break;
+ }
+ ret = 0;
+ bytes -= chunk_size;
+ offset += chunk_size;
+ num_written += chunk_size;
+ msleep(ISL12026_NVMEM_WRITE_TIME);
+ }
+
+ mutex_unlock(&priv->rtc->ops_lock);
+
+ return ret;
+}
+
+static void isl12026_force_power_modes(struct i2c_client *client)
+{
+ int ret;
+ int pwr, requested_pwr;
+ u32 bsw_val, sbib_val;
+ bool set_bsw, set_sbib;
+
+ /*
+ * If we can read the of_property, set the specified value.
+ * If there is an error reading the of_property (likely
+ * because it does not exist), keep the current value.
+ */
+ ret = of_property_read_u32(client->dev.of_node,
+ "isil,pwr-bsw", &bsw_val);
+ set_bsw = (ret == 0);
+
+ ret = of_property_read_u32(client->dev.of_node,
+ "isil,pwr-sbib", &sbib_val);
+ set_sbib = (ret == 0);
+
+ /* Check if PWR.BSW and/or PWR.SBIB need specified values */
+ if (!set_bsw && !set_sbib)
+ return;
+
+ pwr = isl12026_read_reg(client, ISL12026_REG_PWR);
+ if (pwr < 0) {
+ dev_warn(&client->dev, "Error: Failed to read PWR %d\n", pwr);
+ return;
+ }
+
+ requested_pwr = pwr;
+
+ if (set_bsw) {
+ if (bsw_val)
+ requested_pwr |= ISL12026_REG_PWR_BSW;
+ else
+ requested_pwr &= ~ISL12026_REG_PWR_BSW;
+ } /* else keep current BSW */
+
+ if (set_sbib) {
+ if (sbib_val)
+ requested_pwr |= ISL12026_REG_PWR_SBIB;
+ else
+ requested_pwr &= ~ISL12026_REG_PWR_SBIB;
+ } /* else keep current SBIB */
+
+ if (pwr >= 0 && pwr != requested_pwr) {
+ dev_dbg(&client->dev, "PWR: %02x\n", pwr);
+ dev_dbg(&client->dev, "Updating PWR to: %02x\n", requested_pwr);
+ isl12026_write_reg(client, ISL12026_REG_PWR, requested_pwr);
+ }
+}
+
+static int isl12026_probe_new(struct i2c_client *client)
+{
+ struct isl12026 *priv;
+ int ret;
+ struct nvmem_config nvm_cfg = {
+ .name = "isl12026-",
+ .base_dev = &client->dev,
+ .stride = 1,
+ .word_size = 1,
+ .size = 512,
+ .reg_read = isl12026_nvm_read,
+ .reg_write = isl12026_nvm_write,
+ };
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENODEV;
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, priv);
+
+ isl12026_force_power_modes(client);
+
+ priv->nvm_client = i2c_new_dummy(client->adapter, ISL12026_EEPROM_ADDR);
+ if (!priv->nvm_client)
+ return -ENOMEM;
+
+ priv->rtc = devm_rtc_allocate_device(&client->dev);
+ ret = PTR_ERR_OR_ZERO(priv->rtc);
+ if (ret)
+ return ret;
+
+ priv->rtc->ops = &isl12026_rtc_ops;
+ nvm_cfg.priv = priv;
+ ret = rtc_nvmem_register(priv->rtc, &nvm_cfg);
+ if (ret)
+ return ret;
+
+ return rtc_register_device(priv->rtc);
+}
+
+static int isl12026_remove(struct i2c_client *client)
+{
+ struct isl12026 *priv = i2c_get_clientdata(client);
+
+ i2c_unregister_device(priv->nvm_client);
+ return 0;
+}
+
+static const struct of_device_id isl12026_dt_match[] = {
+ { .compatible = "isil,isl12026" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, isl12026_dt_match);
+
+static struct i2c_driver isl12026_driver = {
+ .driver = {
+ .name = "rtc-isl12026",
+ .of_match_table = isl12026_dt_match,
+ },
+ .probe_new = isl12026_probe_new,
+ .remove = isl12026_remove,
+};
+
+module_i2c_driver(isl12026_driver);
+
+MODULE_DESCRIPTION("ISL 12026 RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index 8dd299c6a1f3..1a2c38cc0178 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -459,6 +459,11 @@ isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
}
/* clear WRTC again */
+ sr = isl1208_i2c_get_sr(client);
+ if (sr < 0) {
+ dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+ return sr;
+ }
sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR,
sr & ~ISL1208_REG_SR_WRTC);
if (sr < 0) {
@@ -630,29 +635,12 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (isl1208_i2c_validate_client(client) < 0)
return -ENODEV;
- if (client->irq > 0) {
- rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
- isl1208_rtc_interrupt,
- IRQF_SHARED | IRQF_ONESHOT,
- isl1208_driver.driver.name,
- client);
- if (!rc) {
- device_init_wakeup(&client->dev, 1);
- enable_irq_wake(client->irq);
- } else {
- dev_err(&client->dev,
- "Unable to request irq %d, no alarm support\n",
- client->irq);
- client->irq = 0;
- }
- }
-
- rtc = devm_rtc_device_register(&client->dev, isl1208_driver.driver.name,
- &isl1208_rtc_ops,
- THIS_MODULE);
+ rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
+ rtc->ops = &isl1208_rtc_ops;
+
i2c_set_clientdata(client, rtc);
rc = isl1208_i2c_get_sr(client);
@@ -669,7 +657,24 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (rc)
return rc;
- return 0;
+ if (client->irq > 0) {
+ rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+ isl1208_rtc_interrupt,
+ IRQF_SHARED | IRQF_ONESHOT,
+ isl1208_driver.driver.name,
+ client);
+ if (!rc) {
+ device_init_wakeup(&client->dev, 1);
+ enable_irq_wake(client->irq);
+ } else {
+ dev_err(&client->dev,
+ "Unable to request irq %d, no alarm support\n",
+ client->irq);
+ client->irq = 0;
+ }
+ }
+
+ return rtc_register_device(rtc);
}
static int
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c
index ff65a7d2b9c9..d0a891777f44 100644
--- a/drivers/rtc/rtc-jz4740.c
+++ b/drivers/rtc/rtc-jz4740.c
@@ -173,7 +173,7 @@ static int jz4740_rtc_read_time(struct device *dev, struct rtc_time *time)
rtc_time_to_tm(secs, time);
- return rtc_valid_tm(time);
+ return 0;
}
static int jz4740_rtc_set_mmss(struct device *dev, unsigned long secs)
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
index 1ae7da5cfc60..4a3c0f3aab14 100644
--- a/drivers/rtc/rtc-lib.c
+++ b/drivers/rtc/rtc-lib.c
@@ -52,13 +52,11 @@ EXPORT_SYMBOL(rtc_year_days);
*/
void rtc_time64_to_tm(time64_t time, struct rtc_time *tm)
{
- unsigned int month, year;
- unsigned long secs;
+ unsigned int month, year, secs;
int days;
/* time must be positive */
- days = div_s64(time, 86400);
- secs = time - (unsigned int) days * 86400;
+ days = div_s64_rem(time, 86400, &secs);
/* day of the week, 1970-01-01 was a Thursday */
tm->tm_wday = (days + 4) % 7;
@@ -67,7 +65,7 @@ void rtc_time64_to_tm(time64_t time, struct rtc_time *tm)
days -= (year - 1970) * 365
+ LEAPS_THRU_END_OF(year - 1)
- LEAPS_THRU_END_OF(1970 - 1);
- if (days < 0) {
+ while (days < 0) {
year -= 1;
days += 365 + is_leap_year(year);
}
diff --git a/drivers/rtc/rtc-lpc24xx.c b/drivers/rtc/rtc-lpc24xx.c
index 59d99596fdeb..14dc7b04fae0 100644
--- a/drivers/rtc/rtc-lpc24xx.c
+++ b/drivers/rtc/rtc-lpc24xx.c
@@ -110,7 +110,7 @@ static int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_year = CT1_YEAR(ct1);
tm->tm_yday = CT2_DOY(ct2);
- return rtc_valid_tm(tm);
+ return 0;
}
static int lpc24xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c
index 887871c3d526..3ba87239aacc 100644
--- a/drivers/rtc/rtc-lpc32xx.c
+++ b/drivers/rtc/rtc-lpc32xx.c
@@ -70,7 +70,7 @@ static int lpc32xx_rtc_read_time(struct device *dev, struct rtc_time *time)
elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT);
rtc_time_to_tm(elapsed_sec, time);
- return rtc_valid_tm(time);
+ return 0;
}
static int lpc32xx_rtc_set_mmss(struct device *dev, unsigned long secs)
diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c
index e04ca54f21e2..045af1135e48 100644
--- a/drivers/rtc/rtc-ls1x.c
+++ b/drivers/rtc/rtc-ls1x.c
@@ -98,7 +98,7 @@ static int ls1x_rtc_read_time(struct device *dev, struct rtc_time *rtm)
ls1x_get_min(v), ls1x_get_sec(v));
rtc_time_to_tm(t, rtm);
- return rtc_valid_tm(rtm);
+ return 0;
}
static int ls1x_rtc_set_time(struct device *dev, struct rtc_time *rtm)
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index c90fba3ed861..ad03e2f12f5d 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -73,7 +73,6 @@
#define M41T80_FEATURE_WD BIT(3) /* Extra watchdog resolution */
#define M41T80_FEATURE_SQ_ALT BIT(4) /* RSx bits are in reg 4 */
-static DEFINE_MUTEX(m41t80_rtc_mutex);
static const struct i2c_device_id m41t80_id[] = {
{ "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT },
{ "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD },
@@ -199,9 +198,9 @@ static irqreturn_t m41t80_handle_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int m41t80_get_datetime(struct i2c_client *client,
- struct rtc_time *tm)
+static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
unsigned char buf[8];
int err, flags;
@@ -230,12 +229,12 @@ static int m41t80_get_datetime(struct i2c_client *client,
/* assume 20YY not 19YY, and ignore the Century Bit */
tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100;
- return rtc_valid_tm(tm);
+ return 0;
}
-/* Sets the given date and time to the real time clock. */
-static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct m41t80_data *clientdata = i2c_get_clientdata(client);
unsigned char buf[8];
int err, flags;
@@ -298,16 +297,6 @@ static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
return 0;
}
-static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
- return m41t80_get_datetime(to_i2c_client(dev), tm);
-}
-
-static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- return m41t80_set_datetime(to_i2c_client(dev), tm);
-}
-
static int m41t80_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -598,6 +587,7 @@ static struct clk *m41t80_sqw_register_clk(struct m41t80_data *m41t80)
*
*****************************************************************************
*/
+static DEFINE_MUTEX(m41t80_rtc_mutex);
static struct i2c_client *save_client;
/* Default margin */
@@ -885,7 +875,6 @@ static int m41t80_probe(struct i2c_client *client,
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
int rc = 0;
- struct rtc_device *rtc = NULL;
struct rtc_time tm;
struct m41t80_data *m41t80_data = NULL;
bool wakeup_source = false;
@@ -909,6 +898,10 @@ static int m41t80_probe(struct i2c_client *client,
m41t80_data->features = id->driver_data;
i2c_set_clientdata(client, m41t80_data);
+ m41t80_data->rtc = devm_rtc_allocate_device(&client->dev);
+ if (IS_ERR(m41t80_data->rtc))
+ return PTR_ERR(m41t80_data->rtc);
+
#ifdef CONFIG_OF
wakeup_source = of_property_read_bool(client->dev.of_node,
"wakeup-source");
@@ -932,15 +925,11 @@ static int m41t80_probe(struct i2c_client *client,
device_init_wakeup(&client->dev, true);
}
- rtc = devm_rtc_device_register(&client->dev, client->name,
- &m41t80_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc))
- return PTR_ERR(rtc);
+ m41t80_data->rtc->ops = &m41t80_rtc_ops;
- m41t80_data->rtc = rtc;
if (client->irq <= 0) {
/* We cannot support UIE mode if we do not have an IRQ line */
- rtc->uie_unsupported = 1;
+ m41t80_data->rtc->uie_unsupported = 1;
}
/* Make sure HT (Halt Update) bit is cleared */
@@ -948,7 +937,7 @@ static int m41t80_probe(struct i2c_client *client,
if (rc >= 0 && rc & M41T80_ALHOUR_HT) {
if (m41t80_data->features & M41T80_FEATURE_HT) {
- m41t80_get_datetime(client, &tm);
+ m41t80_rtc_read_time(&client->dev, &tm);
dev_info(&client->dev, "HT bit was set!\n");
dev_info(&client->dev,
"Power Down at %04i-%02i-%02i %02i:%02i:%02i\n",
@@ -993,6 +982,11 @@ static int m41t80_probe(struct i2c_client *client,
if (m41t80_data->features & M41T80_FEATURE_SQ)
m41t80_sqw_register_clk(m41t80_data);
#endif
+
+ rc = rtc_register_device(m41t80_data->rtc);
+ if (rc)
+ return rc;
+
return 0;
}
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
index 5ac45fc1a787..4a08a9dabc82 100644
--- a/drivers/rtc/rtc-m41t93.c
+++ b/drivers/rtc/rtc-m41t93.c
@@ -159,7 +159,7 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
tm->tm_hour, tm->tm_mday,
tm->tm_mon, tm->tm_year, tm->tm_wday);
- return ret < 0 ? ret : rtc_valid_tm(tm);
+ return ret;
}
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c
index 1f0eb79e69f9..bab82b4be356 100644
--- a/drivers/rtc/rtc-m41t94.c
+++ b/drivers/rtc/rtc-m41t94.c
@@ -99,8 +99,7 @@ static int m41t94_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_hour, tm->tm_mday,
tm->tm_mon, tm->tm_year, tm->tm_wday);
- /* initial clock setting can be undefined */
- return rtc_valid_tm(tm);
+ return 0;
}
static const struct rtc_class_ops m41t94_rtc_ops = {
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c
index 810f4ea481e4..0cf6507de3c7 100644
--- a/drivers/rtc/rtc-m48t35.c
+++ b/drivers/rtc/rtc-m48t35.c
@@ -84,7 +84,7 @@ static int m48t35_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_year += 100;
tm->tm_mon--;
- return rtc_valid_tm(tm);
+ return 0;
}
static int m48t35_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index d99a705bec07..216fac62c888 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -105,7 +105,7 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n",
tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
- return rtc_valid_tm(tm);
+ return 0;
}
static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -334,16 +334,16 @@ static const struct rtc_class_ops m48t02_rtc_ops = {
.set_time = m48t59_rtc_set_time,
};
-static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t size)
+static int m48t59_nvram_read(void *priv, unsigned int offset, void *val,
+ size_t size)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct platform_device *pdev = to_platform_device(dev);
+ struct platform_device *pdev = priv;
+ struct device *dev = &pdev->dev;
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
ssize_t cnt = 0;
unsigned long flags;
+ u8 *buf = val;
spin_lock_irqsave(&m48t59->lock, flags);
@@ -352,19 +352,19 @@ static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj,
spin_unlock_irqrestore(&m48t59->lock, flags);
- return cnt;
+ return 0;
}
-static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t size)
+static int m48t59_nvram_write(void *priv, unsigned int offset, void *val,
+ size_t size)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct platform_device *pdev = to_platform_device(dev);
+ struct platform_device *pdev = priv;
+ struct device *dev = &pdev->dev;
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
ssize_t cnt = 0;
unsigned long flags;
+ u8 *buf = val;
spin_lock_irqsave(&m48t59->lock, flags);
@@ -373,18 +373,9 @@ static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj,
spin_unlock_irqrestore(&m48t59->lock, flags);
- return cnt;
+ return 0;
}
-static struct bin_attribute m48t59_nvram_attr = {
- .attr = {
- .name = "nvram",
- .mode = S_IRUGO | S_IWUSR,
- },
- .read = m48t59_nvram_read,
- .write = m48t59_nvram_write,
-};
-
static int m48t59_rtc_probe(struct platform_device *pdev)
{
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
@@ -393,6 +384,14 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
int ret = -ENOMEM;
char *name;
const struct rtc_class_ops *ops;
+ struct nvmem_config nvmem_cfg = {
+ .name = "m48t59-",
+ .word_size = 1,
+ .stride = 1,
+ .reg_read = m48t59_nvram_read,
+ .reg_write = m48t59_nvram_write,
+ .priv = pdev,
+ };
/* This chip could be memory-mapped or I/O-mapped */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -480,23 +479,22 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
spin_lock_init(&m48t59->lock);
platform_set_drvdata(pdev, m48t59);
- m48t59->rtc = devm_rtc_device_register(&pdev->dev, name, ops,
- THIS_MODULE);
+ m48t59->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(m48t59->rtc))
return PTR_ERR(m48t59->rtc);
- m48t59_nvram_attr.size = pdata->offset;
+ m48t59->rtc->nvram_old_abi = true;
+ m48t59->rtc->ops = ops;
- ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
+ nvmem_cfg.size = pdata->offset;
+ ret = rtc_nvmem_register(m48t59->rtc, &nvmem_cfg);
if (ret)
return ret;
- return 0;
-}
+ ret = rtc_register_device(m48t59->rtc);
+ if (ret)
+ return ret;
-static int m48t59_rtc_remove(struct platform_device *pdev)
-{
- sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
return 0;
}
@@ -508,7 +506,6 @@ static struct platform_driver m48t59_rtc_driver = {
.name = "rtc-m48t59",
},
.probe = m48t59_rtc_probe,
- .remove = m48t59_rtc_remove,
};
module_platform_driver(m48t59_rtc_driver);
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index d9aea9b6d9cd..a9533535c3b7 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -100,7 +100,7 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
if (m48t86_readb(dev, M48T86_HOUR) & 0x80)
tm->tm_hour += 12;
- return rtc_valid_tm(tm);
+ return 0;
}
static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -218,21 +218,21 @@ static bool m48t86_verify_chip(struct platform_device *pdev)
return false;
}
-static struct nvmem_config m48t86_nvmem_cfg = {
- .name = "m48t86_nvram",
- .word_size = 1,
- .stride = 1,
- .size = M48T86_NVRAM_LEN,
- .reg_read = m48t86_nvram_read,
- .reg_write = m48t86_nvram_write,
-};
-
static int m48t86_rtc_probe(struct platform_device *pdev)
{
struct m48t86_rtc_info *info;
struct resource *res;
unsigned char reg;
int err;
+ struct nvmem_config m48t86_nvmem_cfg = {
+ .name = "m48t86_nvram",
+ .word_size = 1,
+ .stride = 1,
+ .size = M48T86_NVRAM_LEN,
+ .reg_read = m48t86_nvram_read,
+ .reg_write = m48t86_nvram_write,
+ .priv = &pdev->dev,
+ };
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info)
@@ -264,15 +264,14 @@ static int m48t86_rtc_probe(struct platform_device *pdev)
return PTR_ERR(info->rtc);
info->rtc->ops = &m48t86_rtc_ops;
-
- m48t86_nvmem_cfg.priv = &pdev->dev;
- info->rtc->nvmem_config = &m48t86_nvmem_cfg;
info->rtc->nvram_old_abi = true;
err = rtc_register_device(info->rtc);
if (err)
return err;
+ rtc_nvmem_register(info->rtc, &m48t86_nvmem_cfg);
+
/* read battery status */
reg = m48t86_readb(&pdev->dev, M48T86_D);
dev_info(&pdev->dev, "battery %s\n",
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c
index cbdc86a560ba..ab60f13fa3ef 100644
--- a/drivers/rtc/rtc-max6900.c
+++ b/drivers/rtc/rtc-max6900.c
@@ -139,8 +139,9 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf)
return -EIO;
}
-static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
+static int max6900_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
int rc;
u8 regs[MAX6900_REG_LEN];
@@ -157,7 +158,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900;
tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]);
- return rtc_valid_tm(tm);
+ return 0;
}
static int max6900_i2c_clear_write_protect(struct i2c_client *client)
@@ -165,9 +166,9 @@ static int max6900_i2c_clear_write_protect(struct i2c_client *client)
return i2c_smbus_write_byte_data(client, MAX6900_REG_CONTROL_WRITE, 0);
}
-static int
-max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
+static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
u8 regs[MAX6900_REG_LEN];
int rc;
@@ -193,16 +194,6 @@ max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
return 0;
}
-static int max6900_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
- return max6900_i2c_read_time(to_i2c_client(dev), tm);
-}
-
-static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- return max6900_i2c_set_time(to_i2c_client(dev), tm);
-}
-
static const struct rtc_class_ops max6900_rtc_ops = {
.read_time = max6900_rtc_read_time,
.set_time = max6900_rtc_set_time,
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c
index 315d09e0f2c1..745827463367 100644
--- a/drivers/rtc/rtc-max6902.c
+++ b/drivers/rtc/rtc-max6902.c
@@ -85,7 +85,7 @@ static int max6902_read_time(struct device *dev, struct rtc_time *dt)
dt->tm_year += century;
dt->tm_year -= 1900;
- return rtc_valid_tm(dt);
+ return 0;
}
static int max6902_set_time(struct device *dev, struct rtc_time *dt)
diff --git a/drivers/rtc/rtc-max6916.c b/drivers/rtc/rtc-max6916.c
index 623ab27b2757..7e908a490cf6 100644
--- a/drivers/rtc/rtc-max6916.c
+++ b/drivers/rtc/rtc-max6916.c
@@ -75,7 +75,7 @@ static int max6916_read_time(struct device *dev, struct rtc_time *dt)
dt->tm_wday = bcd2bin(buf[5]) - 1;
dt->tm_year = bcd2bin(buf[6]) + 100;
- return rtc_valid_tm(dt);
+ return 0;
}
static int max6916_set_time(struct device *dev, struct rtc_time *dt)
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 182fdd00e290..cefde273fae6 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -364,11 +364,9 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm)
max77686_rtc_data_to_tm(data, tm, info);
- ret = rtc_valid_tm(tm);
-
out:
mutex_unlock(&info->lock);
- return ret;
+ return 0;
}
static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
index db984d4bf952..e8cee123e8aa 100644
--- a/drivers/rtc/rtc-max8997.c
+++ b/drivers/rtc/rtc-max8997.c
@@ -153,7 +153,7 @@ static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm)
max8997_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
- return rtc_valid_tm(tm);
+ return 0;
}
static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c
index 30804b00985e..d8c0f9b3f87d 100644
--- a/drivers/rtc/rtc-max8998.c
+++ b/drivers/rtc/rtc-max8998.c
@@ -120,7 +120,7 @@ static int max8998_rtc_read_time(struct device *dev, struct rtc_time *tm)
max8998_data_to_tm(data, tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int max8998_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index 30b8ef6a3676..1f892b238ddb 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -85,7 +85,7 @@ static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time64_to_tm((time64_t)days1 * SEC_PER_DAY + seconds, tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int mc13xxx_rtc_set_mmss(struct device *dev, time64_t secs)
diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c
index 77f21331ae21..00e11c1b2186 100644
--- a/drivers/rtc/rtc-mcp795.c
+++ b/drivers/rtc/rtc-mcp795.c
@@ -82,7 +82,7 @@ static int mcp795_rtcc_write(struct device *dev, u8 addr, u8 *data, u8 count)
{
struct spi_device *spi = to_spi_device(dev);
int ret;
- u8 tx[2 + count];
+ u8 tx[257];
tx[0] = MCP795_WRITE;
tx[1] = addr;
@@ -262,7 +262,7 @@ static int mcp795_read_time(struct device *dev, struct rtc_time *tim)
tim->tm_year + 1900, tim->tm_mon, tim->tm_mday,
tim->tm_wday, tim->tm_hour, tim->tm_min, tim->tm_sec);
- return rtc_valid_tm(tim);
+ return 0;
}
static int mcp795_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index 4ca4daa0b8f3..dd0364293bc0 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -122,7 +122,7 @@ static int mpc5121_rtc_read_time(struct device *dev, struct rtc_time *tm)
*/
mpc5121_rtc_update_smh(regs, tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
index 7334c44fa7c3..fcb9de5218b2 100644
--- a/drivers/rtc/rtc-mrst.c
+++ b/drivers/rtc/rtc-mrst.c
@@ -105,7 +105,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
/* Adjust for the 1972/1900 */
time->tm_year += 72;
time->tm_mon--;
- return rtc_valid_tm(time);
+ return 0;
}
static int mrst_set_time(struct device *dev, struct rtc_time *time)
@@ -122,7 +122,7 @@ static int mrst_set_time(struct device *dev, struct rtc_time *time)
min = time->tm_min;
sec = time->tm_sec;
- if (yrs < 72 || yrs > 138)
+ if (yrs < 72 || yrs > 172)
return -EINVAL;
yrs -= 72;
diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c
index c1c5c4e3b3b4..0c72a2e8ec67 100644
--- a/drivers/rtc/rtc-msm6242.c
+++ b/drivers/rtc/rtc-msm6242.c
@@ -155,7 +155,7 @@ static int msm6242_read_time(struct device *dev, struct rtc_time *tm)
msm6242_unlock(priv);
- return rtc_valid_tm(tm);
+ return 0;
}
static int msm6242_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-mt7622.c b/drivers/rtc/rtc-mt7622.c
index d79b9ae4d237..fd0cea722286 100644
--- a/drivers/rtc/rtc-mt7622.c
+++ b/drivers/rtc/rtc-mt7622.c
@@ -232,7 +232,7 @@ static int mtk_rtc_gettime(struct device *dev, struct rtc_time *tm)
mtk_rtc_get_alarm_or_time(hw, tm, MTK_TC);
- return rtc_valid_tm(tm);
+ return 0;
}
static int mtk_rtc_settime(struct device *dev, struct rtc_time *tm)
@@ -307,6 +307,7 @@ static const struct of_device_id mtk_rtc_match[] = {
{ .compatible = "mediatek,soc-rtc" },
{},
};
+MODULE_DEVICE_TABLE(of, mtk_rtc_match);
static int mtk_rtc_probe(struct platform_device *pdev)
{
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index 79bb28617d45..bc52dbb0c0e2 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -94,7 +94,7 @@ static int mv_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* hw counts from year 2000, but tm_year is relative to 1900 */
tm->tm_year = bcd2bin(year) + 100;
- return rtc_valid_tm(tm);
+ return 0;
}
static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
@@ -223,7 +223,6 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
struct resource *res;
struct rtc_plat_data *pdata;
u32 rtc_time;
- u32 rtc_date;
int ret = 0;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
@@ -259,17 +258,6 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
}
}
- /*
- * A date after January 19th, 2038 does not fit on 32 bits and
- * will confuse the kernel and userspace. Reset to a sane date
- * (January 1st, 2013) if we're after 2038.
- */
- rtc_date = readl(pdata->ioaddr + RTC_DATE_REG_OFFS);
- if (bcd2bin((rtc_date >> RTC_YEAR_OFFS) & 0xff) >= 38) {
- dev_info(&pdev->dev, "invalid RTC date, resetting to January 1st, 2013\n");
- writel(0x130101, pdata->ioaddr + RTC_DATE_REG_OFFS);
- }
-
pdata->irq = platform_get_irq(pdev, 0);
platform_set_drvdata(pdev, pdata);
diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c
index 784221dfc9c7..9e14efb990b2 100644
--- a/drivers/rtc/rtc-mxc_v2.c
+++ b/drivers/rtc/rtc-mxc_v2.c
@@ -273,7 +273,7 @@ static const struct rtc_class_ops mxc_rtc_ops = {
.alarm_irq_enable = mxc_rtc_alarm_irq_enable,
};
-static int mxc_rtc_wait_for_flag(void *__iomem ioaddr, int flag)
+static int mxc_rtc_wait_for_flag(void __iomem *ioaddr, int flag)
{
unsigned int timeout = REG_READ_TIMEOUT;
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c
index 4ed81117cf5f..7da664a77181 100644
--- a/drivers/rtc/rtc-nuc900.c
+++ b/drivers/rtc/rtc-nuc900.c
@@ -102,8 +102,8 @@ static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc)
return NULL;
}
-static int nuc900_rtc_bcd2bin(unsigned int timereg,
- unsigned int calreg, struct rtc_time *tm)
+static void nuc900_rtc_bcd2bin(unsigned int timereg,
+ unsigned int calreg, struct rtc_time *tm)
{
tm->tm_mday = bcd2bin(calreg >> 0);
tm->tm_mon = bcd2bin(calreg >> 8);
@@ -112,8 +112,6 @@ static int nuc900_rtc_bcd2bin(unsigned int timereg,
tm->tm_sec = bcd2bin(timereg >> 0);
tm->tm_min = bcd2bin(timereg >> 8);
tm->tm_hour = bcd2bin(timereg >> 16);
-
- return rtc_valid_tm(tm);
}
static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm,
@@ -156,7 +154,9 @@ static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm)
timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR);
clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR);
- return nuc900_rtc_bcd2bin(timeval, clrval, tm);
+ nuc900_rtc_bcd2bin(timeval, clrval, tm);
+
+ return 0;
}
static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -189,7 +189,9 @@ static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR);
carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR);
- return nuc900_rtc_bcd2bin(timeval, carval, &alrm->time);
+ nuc900_rtc_bcd2bin(timeval, carval, &alrm->time);
+
+ return rtc_valid_tm(&alrm->time);
}
static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 09ef802d6e54..39086398833e 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -273,9 +273,6 @@ static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
/* this hardware doesn't support "don't care" alarm fields */
static int tm2bcd(struct rtc_time *tm)
{
- if (rtc_valid_tm(tm) != 0)
- return -EINVAL;
-
tm->tm_sec = bin2bcd(tm->tm_sec);
tm->tm_min = bin2bcd(tm->tm_min);
tm->tm_hour = bin2bcd(tm->tm_hour);
@@ -850,7 +847,6 @@ static int omap_rtc_probe(struct platform_device *pdev)
rtc->rtc->ops = &omap_rtc_ops;
omap_rtc_nvmem_config.priv = rtc;
- rtc->rtc->nvmem_config = &omap_rtc_nvmem_config;
/* handle periodic and alarm irqs */
ret = devm_request_irq(&pdev->dev, rtc->irq_timer, rtc_irq, 0,
@@ -886,6 +882,8 @@ static int omap_rtc_probe(struct platform_device *pdev)
if (ret)
goto err;
+ rtc_nvmem_register(rtc->rtc, &omap_rtc_nvmem_config);
+
return 0;
err:
diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c
index c4433240d8a9..c05f524ba9af 100644
--- a/drivers/rtc/rtc-pcap.c
+++ b/drivers/rtc/rtc-pcap.c
@@ -95,7 +95,7 @@ static int pcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time_to_tm(secs, tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int pcap_rtc_set_mmss(struct device *dev, unsigned long secs)
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index 8895f77726e8..e5222c5d8223 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -289,7 +289,7 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- return rtc_valid_tm(tm);
+ return 0;
}
static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index f33447c5db85..e83be1852c2f 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -111,7 +111,7 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- return rtc_valid_tm(tm);
+ return 0;
}
static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c
index 00c31c91b245..ef72b0c389d7 100644
--- a/drivers/rtc/rtc-pcf50633.c
+++ b/drivers/rtc/rtc-pcf50633.c
@@ -135,7 +135,7 @@ static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mday, tm->tm_mon, tm->tm_year,
tm->tm_hour, tm->tm_min, tm->tm_sec);
- return rtc_valid_tm(tm);
+ return 0;
}
static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index a06dff994c83..49bcbb3d4a69 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -70,7 +70,7 @@ static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
s32 ret;
/* start the clock */
- ctrl1 &= PCF85063_REG_CTRL1_STOP;
+ ctrl1 &= ~PCF85063_REG_CTRL1_STOP;
ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
if (ret < 0) {
@@ -81,8 +81,9 @@ static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
return 0;
}
-static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
int rc;
u8 regs[7];
@@ -114,11 +115,12 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_year = bcd2bin(regs[6]);
tm->tm_year += 100;
- return rtc_valid_tm(tm);
+ return 0;
}
-static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
int rc;
u8 regs[7];
u8 ctrl1;
@@ -172,16 +174,6 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return 0;
}
-static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
- return pcf85063_get_datetime(to_i2c_client(dev), tm);
-}
-
-static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- return pcf85063_set_datetime(to_i2c_client(dev), tm);
-}
-
static const struct rtc_class_ops pcf85063_rtc_ops = {
.read_time = pcf85063_rtc_read_time,
.set_time = pcf85063_rtc_set_time
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c
index c312af0db729..453615f8ac9a 100644
--- a/drivers/rtc/rtc-pcf8523.c
+++ b/drivers/rtc/rtc-pcf8523.c
@@ -192,7 +192,7 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon = bcd2bin(regs[5] & 0x1f) - 1;
tm->tm_year = bcd2bin(regs[6]) + 100;
- return rtc_valid_tm(tm);
+ return 0;
}
static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c
index ea04e9f0930b..c04a1edcd571 100644
--- a/drivers/rtc/rtc-pcf85363.c
+++ b/drivers/rtc/rtc-pcf85363.c
@@ -73,6 +73,43 @@
#define CTRL_RESETS 0x2f
#define CTRL_RAM 0x40
+#define ALRM_SEC_A1E BIT(0)
+#define ALRM_MIN_A1E BIT(1)
+#define ALRM_HR_A1E BIT(2)
+#define ALRM_DAY_A1E BIT(3)
+#define ALRM_MON_A1E BIT(4)
+#define ALRM_MIN_A2E BIT(5)
+#define ALRM_HR_A2E BIT(6)
+#define ALRM_DAY_A2E BIT(7)
+
+#define INT_WDIE BIT(0)
+#define INT_BSIE BIT(1)
+#define INT_TSRIE BIT(2)
+#define INT_A2IE BIT(3)
+#define INT_A1IE BIT(4)
+#define INT_OIE BIT(5)
+#define INT_PIE BIT(6)
+#define INT_ILP BIT(7)
+
+#define FLAGS_TSR1F BIT(0)
+#define FLAGS_TSR2F BIT(1)
+#define FLAGS_TSR3F BIT(2)
+#define FLAGS_BSF BIT(3)
+#define FLAGS_WDF BIT(4)
+#define FLAGS_A1F BIT(5)
+#define FLAGS_A2F BIT(6)
+#define FLAGS_PIF BIT(7)
+
+#define PIN_IO_INTAPM GENMASK(1, 0)
+#define PIN_IO_INTA_CLK 0
+#define PIN_IO_INTA_BAT 1
+#define PIN_IO_INTA_OUT 2
+#define PIN_IO_INTA_HIZ 3
+
+#define STOP_EN_STOP BIT(0)
+
+#define RESET_CPR 0xa4
+
#define NVRAM_SIZE 0x40
static struct i2c_driver pcf85363_driver;
@@ -80,7 +117,6 @@ static struct i2c_driver pcf85363_driver;
struct pcf85363 {
struct device *dev;
struct rtc_device *rtc;
- struct nvmem_config nvmem_cfg;
struct regmap *regmap;
};
@@ -116,8 +152,12 @@ static int pcf85363_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
- unsigned char buf[DT_YEARS + 1];
- int len = sizeof(buf);
+ unsigned char tmp[11];
+ unsigned char *buf = &tmp[2];
+ int ret;
+
+ tmp[0] = STOP_EN_STOP;
+ tmp[1] = RESET_CPR;
buf[DT_100THS] = 0;
buf[DT_SECS] = bin2bcd(tm->tm_sec);
@@ -128,8 +168,116 @@ static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm)
buf[DT_MONTHS] = bin2bcd(tm->tm_mon + 1);
buf[DT_YEARS] = bin2bcd(tm->tm_year % 100);
- return regmap_bulk_write(pcf85363->regmap, DT_100THS,
- buf, len);
+ ret = regmap_bulk_write(pcf85363->regmap, CTRL_STOP_EN,
+ tmp, sizeof(tmp));
+ if (ret)
+ return ret;
+
+ return regmap_write(pcf85363->regmap, CTRL_STOP_EN, 0);
+}
+
+static int pcf85363_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
+ unsigned char buf[DT_MONTH_ALM1 - DT_SECOND_ALM1 + 1];
+ unsigned int val;
+ int ret;
+
+ ret = regmap_bulk_read(pcf85363->regmap, DT_SECOND_ALM1, buf,
+ sizeof(buf));
+ if (ret)
+ return ret;
+
+ alrm->time.tm_sec = bcd2bin(buf[0]);
+ alrm->time.tm_min = bcd2bin(buf[1]);
+ alrm->time.tm_hour = bcd2bin(buf[2]);
+ alrm->time.tm_mday = bcd2bin(buf[3]);
+ alrm->time.tm_mon = bcd2bin(buf[4]) - 1;
+
+ ret = regmap_read(pcf85363->regmap, CTRL_INTA_EN, &val);
+ if (ret)
+ return ret;
+
+ alrm->enabled = !!(val & INT_A1IE);
+
+ return 0;
+}
+
+static int _pcf85363_rtc_alarm_irq_enable(struct pcf85363 *pcf85363, unsigned
+ int enabled)
+{
+ unsigned int alarm_flags = ALRM_SEC_A1E | ALRM_MIN_A1E | ALRM_HR_A1E |
+ ALRM_DAY_A1E | ALRM_MON_A1E;
+ int ret;
+
+ ret = regmap_update_bits(pcf85363->regmap, DT_ALARM_EN, alarm_flags,
+ enabled ? alarm_flags : 0);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(pcf85363->regmap, CTRL_INTA_EN,
+ INT_A1IE, enabled ? INT_A1IE : 0);
+
+ if (ret || enabled)
+ return ret;
+
+ /* clear current flags */
+ return regmap_update_bits(pcf85363->regmap, CTRL_FLAGS, FLAGS_A1F, 0);
+}
+
+static int pcf85363_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
+{
+ struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
+
+ return _pcf85363_rtc_alarm_irq_enable(pcf85363, enabled);
+}
+
+static int pcf85363_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
+ unsigned char buf[DT_MONTH_ALM1 - DT_SECOND_ALM1 + 1];
+ int ret;
+
+ buf[0] = bin2bcd(alrm->time.tm_sec);
+ buf[1] = bin2bcd(alrm->time.tm_min);
+ buf[2] = bin2bcd(alrm->time.tm_hour);
+ buf[3] = bin2bcd(alrm->time.tm_mday);
+ buf[4] = bin2bcd(alrm->time.tm_mon + 1);
+
+ /*
+ * Disable the alarm interrupt before changing the value to avoid
+ * spurious interrupts
+ */
+ ret = _pcf85363_rtc_alarm_irq_enable(pcf85363, 0);
+ if (ret)
+ return ret;
+
+ ret = regmap_bulk_write(pcf85363->regmap, DT_SECOND_ALM1, buf,
+ sizeof(buf));
+ if (ret)
+ return ret;
+
+ return _pcf85363_rtc_alarm_irq_enable(pcf85363, alrm->enabled);
+}
+
+static irqreturn_t pcf85363_rtc_handle_irq(int irq, void *dev_id)
+{
+ struct pcf85363 *pcf85363 = i2c_get_clientdata(dev_id);
+ unsigned int flags;
+ int err;
+
+ err = regmap_read(pcf85363->regmap, CTRL_FLAGS, &flags);
+ if (err)
+ return IRQ_NONE;
+
+ if (flags & FLAGS_A1F) {
+ rtc_update_irq(pcf85363->rtc, 1, RTC_IRQF | RTC_AF);
+ regmap_update_bits(pcf85363->regmap, CTRL_FLAGS, FLAGS_A1F, 0);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
}
static const struct rtc_class_ops rtc_ops = {
@@ -137,6 +285,14 @@ static const struct rtc_class_ops rtc_ops = {
.set_time = pcf85363_rtc_set_time,
};
+static const struct rtc_class_ops rtc_ops_alarm = {
+ .read_time = pcf85363_rtc_read_time,
+ .set_time = pcf85363_rtc_set_time,
+ .read_alarm = pcf85363_rtc_read_alarm,
+ .set_alarm = pcf85363_rtc_set_alarm,
+ .alarm_irq_enable = pcf85363_rtc_alarm_irq_enable,
+};
+
static int pcf85363_nvram_read(void *priv, unsigned int offset, void *val,
size_t bytes)
{
@@ -158,12 +314,22 @@ static int pcf85363_nvram_write(void *priv, unsigned int offset, void *val,
static const struct regmap_config regmap_config = {
.reg_bits = 8,
.val_bits = 8,
+ .max_register = 0x7f,
};
static int pcf85363_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pcf85363 *pcf85363;
+ struct nvmem_config nvmem_cfg = {
+ .name = "pcf85363-",
+ .word_size = 1,
+ .stride = 1,
+ .size = NVRAM_SIZE,
+ .reg_read = pcf85363_nvram_read,
+ .reg_write = pcf85363_nvram_write,
+ };
+ int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
@@ -186,17 +352,28 @@ static int pcf85363_probe(struct i2c_client *client,
if (IS_ERR(pcf85363->rtc))
return PTR_ERR(pcf85363->rtc);
- pcf85363->nvmem_cfg.name = "pcf85363-";
- pcf85363->nvmem_cfg.word_size = 1;
- pcf85363->nvmem_cfg.stride = 1;
- pcf85363->nvmem_cfg.size = NVRAM_SIZE;
- pcf85363->nvmem_cfg.reg_read = pcf85363_nvram_read;
- pcf85363->nvmem_cfg.reg_write = pcf85363_nvram_write;
- pcf85363->nvmem_cfg.priv = pcf85363;
- pcf85363->rtc->nvmem_config = &pcf85363->nvmem_cfg;
pcf85363->rtc->ops = &rtc_ops;
- return rtc_register_device(pcf85363->rtc);
+ if (client->irq > 0) {
+ regmap_write(pcf85363->regmap, CTRL_FLAGS, 0);
+ regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO,
+ PIN_IO_INTA_OUT, PIN_IO_INTAPM);
+ ret = devm_request_threaded_irq(pcf85363->dev, client->irq,
+ NULL, pcf85363_rtc_handle_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "pcf85363", client);
+ if (ret)
+ dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
+ else
+ pcf85363->rtc->ops = &rtc_ops_alarm;
+ }
+
+ ret = rtc_register_device(pcf85363->rtc);
+
+ nvmem_cfg.priv = pcf85363;
+ rtc_nvmem_register(pcf85363->rtc, &nvmem_cfg);
+
+ return ret;
}
static const struct of_device_id dev_ids[] = {
diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c
index 5cfb6df5c430..3c08eab4f1a8 100644
--- a/drivers/rtc/rtc-pic32.c
+++ b/drivers/rtc/rtc-pic32.c
@@ -175,7 +175,7 @@ static int pic32_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
clk_disable(pdata->clk);
- return rtc_valid_tm(rtc_tm);
+ return 0;
}
static int pic32_rtc_settime(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c
index fac835530671..29358a045925 100644
--- a/drivers/rtc/rtc-pm8xxx.c
+++ b/drivers/rtc/rtc-pm8xxx.c
@@ -74,16 +74,18 @@ struct pm8xxx_rtc {
/*
* Steps to write the RTC registers.
* 1. Disable alarm if enabled.
- * 2. Write 0x00 to LSB.
- * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0].
- * 4. Enable alarm if disabled in step 1.
+ * 2. Disable rtc if enabled.
+ * 3. Write 0x00 to LSB.
+ * 4. Write Byte[1], Byte[2], Byte[3] then Byte[0].
+ * 5. Enable rtc if disabled in step 2.
+ * 6. Enable alarm if disabled in step 1.
*/
static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
int rc, i;
unsigned long secs, irq_flags;
- u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0;
- unsigned int ctrl_reg;
+ u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0, rtc_disabled = 0;
+ unsigned int ctrl_reg, rtc_ctrl_reg;
struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
@@ -92,23 +94,38 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
rtc_tm_to_time(tm, &secs);
+ dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
+
for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
value[i] = secs & 0xFF;
secs >>= 8;
}
- dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
-
spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
- rc = regmap_read(rtc_dd->regmap, regs->ctrl, &ctrl_reg);
+ rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg);
if (rc)
goto rtc_rw_fail;
if (ctrl_reg & regs->alarm_en) {
alarm_enabled = 1;
ctrl_reg &= ~regs->alarm_en;
- rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg);
+ rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
+ if (rc) {
+ dev_err(dev, "Write to RTC Alarm control register failed\n");
+ goto rtc_rw_fail;
+ }
+ }
+
+ /* Disable RTC H/w before writing on RTC register */
+ rc = regmap_read(rtc_dd->regmap, regs->ctrl, &rtc_ctrl_reg);
+ if (rc)
+ goto rtc_rw_fail;
+
+ if (rtc_ctrl_reg & PM8xxx_RTC_ENABLE) {
+ rtc_disabled = 1;
+ rtc_ctrl_reg &= ~PM8xxx_RTC_ENABLE;
+ rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg);
if (rc) {
dev_err(dev, "Write to RTC control register failed\n");
goto rtc_rw_fail;
@@ -137,11 +154,21 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
goto rtc_rw_fail;
}
+ /* Enable RTC H/w after writing on RTC register */
+ if (rtc_disabled) {
+ rtc_ctrl_reg |= PM8xxx_RTC_ENABLE;
+ rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg);
+ if (rc) {
+ dev_err(dev, "Write to RTC control register failed\n");
+ goto rtc_rw_fail;
+ }
+ }
+
if (alarm_enabled) {
ctrl_reg |= regs->alarm_en;
- rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg);
+ rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
if (rc) {
- dev_err(dev, "Write to RTC control register failed\n");
+ dev_err(dev, "Write to RTC Alarm control register failed\n");
goto rtc_rw_fail;
}
}
@@ -190,12 +217,6 @@ static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time_to_tm(secs, tm);
- rc = rtc_valid_tm(tm);
- if (rc < 0) {
- dev_err(dev, "Invalid time read from RTC\n");
- return rc;
- }
-
dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n",
secs, tm->tm_hour, tm->tm_min, tm->tm_sec,
tm->tm_mday, tm->tm_mon, tm->tm_year);
diff --git a/drivers/rtc/rtc-ps3.c b/drivers/rtc/rtc-ps3.c
index 6a8f5d758eac..347288bff438 100644
--- a/drivers/rtc/rtc-ps3.c
+++ b/drivers/rtc/rtc-ps3.c
@@ -41,7 +41,7 @@ static u64 read_rtc(void)
static int ps3_get_time(struct device *dev, struct rtc_time *tm)
{
rtc_time_to_tm(read_rtc() + ps3_os_area_get_rtc_diff(), tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int ps3_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-r7301.c b/drivers/rtc/rtc-r7301.c
index 500e8c8a2605..169704b2ce13 100644
--- a/drivers/rtc/rtc-r7301.c
+++ b/drivers/rtc/rtc-r7301.c
@@ -224,7 +224,7 @@ static int rtc7301_read_time(struct device *dev, struct rtc_time *tm)
spin_unlock_irqrestore(&priv->lock, flags);
- return err ? err : rtc_valid_tm(tm);
+ return err;
}
static int rtc7301_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c
index b6c5eb97051c..a39ccd1cf6e8 100644
--- a/drivers/rtc/rtc-r9701.c
+++ b/drivers/rtc/rtc-r9701.c
@@ -92,7 +92,7 @@ static int r9701_get_datetime(struct device *dev, struct rtc_time *dt)
* according to the data sheet. make sure they are valid.
*/
- return rtc_valid_tm(dt);
+ return 0;
}
static int r9701_set_datetime(struct device *dev, struct rtc_time *dt)
diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c
index 35c9aada07c8..739c0d42e835 100644
--- a/drivers/rtc/rtc-rk808.c
+++ b/drivers/rtc/rtc-rk808.c
@@ -375,7 +375,6 @@ static int rk808_rtc_probe(struct platform_device *pdev)
{
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
struct rk808_rtc *rk808_rtc;
- struct rtc_time tm;
int ret;
rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL);
@@ -404,24 +403,13 @@ static int rk808_rtc_probe(struct platform_device *pdev)
return ret;
}
- /* set init time */
- ret = rk808_rtc_readtime(&pdev->dev, &tm);
- if (ret) {
- dev_err(&pdev->dev, "Failed to read RTC time\n");
- return ret;
- }
- ret = rtc_valid_tm(&tm);
- if (ret)
- dev_warn(&pdev->dev, "invalid date/time\n");
-
device_init_wakeup(&pdev->dev, 1);
- rk808_rtc->rtc = devm_rtc_device_register(&pdev->dev, "rk808-rtc",
- &rk808_rtc_ops, THIS_MODULE);
- if (IS_ERR(rk808_rtc->rtc)) {
- ret = PTR_ERR(rk808_rtc->rtc);
- return ret;
- }
+ rk808_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(rk808_rtc->rtc))
+ return PTR_ERR(rk808_rtc->rtc);
+
+ rk808_rtc->rtc->ops = &rk808_rtc_ops;
rk808_rtc->irq = platform_get_irq(pdev, 0);
if (rk808_rtc->irq < 0) {
@@ -438,9 +426,10 @@ static int rk808_rtc_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
rk808_rtc->irq, ret);
+ return ret;
}
- return ret;
+ return rtc_register_device(rk808_rtc->rtc);
}
static struct platform_driver rk808_rtc_driver = {
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c
index 026035373ae6..f1c160fe7d37 100644
--- a/drivers/rtc/rtc-rp5c01.c
+++ b/drivers/rtc/rtc-rp5c01.c
@@ -64,7 +64,6 @@ struct rp5c01_priv {
u32 __iomem *regs;
struct rtc_device *rtc;
spinlock_t lock; /* against concurrent RTC/NVRAM access */
- struct bin_attribute nvram_attr;
};
static inline unsigned int rp5c01_read(struct rp5c01_priv *priv,
@@ -116,7 +115,7 @@ static int rp5c01_read_time(struct device *dev, struct rtc_time *tm)
rp5c01_unlock(priv);
spin_unlock_irq(&priv->lock);
- return rtc_valid_tm(tm);
+ return 0;
}
static int rp5c01_set_time(struct device *dev, struct rtc_time *tm)
@@ -160,17 +159,15 @@ static const struct rtc_class_ops rp5c01_rtc_ops = {
* byte is stored in BLOCK10, the low nibble in BLOCK11.
*/
-static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t size)
+static int rp5c01_nvram_read(void *_priv, unsigned int pos, void *val,
+ size_t bytes)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct rp5c01_priv *priv = dev_get_drvdata(dev);
- ssize_t count;
+ struct rp5c01_priv *priv = _priv;
+ u8 *buf = val;
spin_lock_irq(&priv->lock);
- for (count = 0; count < size; count++) {
+ for (; bytes; bytes--) {
u8 data;
rp5c01_write(priv,
@@ -187,20 +184,18 @@ static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj,
}
spin_unlock_irq(&priv->lock);
- return count;
+ return 0;
}
-static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t size)
+static int rp5c01_nvram_write(void *_priv, unsigned int pos, void *val,
+ size_t bytes)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct rp5c01_priv *priv = dev_get_drvdata(dev);
- ssize_t count;
+ struct rp5c01_priv *priv = _priv;
+ u8 *buf = val;
spin_lock_irq(&priv->lock);
- for (count = 0; count < size; count++) {
+ for (; bytes; bytes--) {
u8 data = *buf++;
rp5c01_write(priv,
@@ -216,7 +211,7 @@ static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj,
}
spin_unlock_irq(&priv->lock);
- return count;
+ return 0;
}
static int __init rp5c01_rtc_probe(struct platform_device *dev)
@@ -225,6 +220,14 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev)
struct rp5c01_priv *priv;
struct rtc_device *rtc;
int error;
+ struct nvmem_config nvmem_cfg = {
+ .name = "rp5c01_nvram",
+ .word_size = 1,
+ .stride = 1,
+ .size = RP5C01_MODE,
+ .reg_read = rp5c01_nvram_read,
+ .reg_write = rp5c01_nvram_write,
+ };
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res)
@@ -238,43 +241,31 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev)
if (!priv->regs)
return -ENOMEM;
- sysfs_bin_attr_init(&priv->nvram_attr);
- priv->nvram_attr.attr.name = "nvram";
- priv->nvram_attr.attr.mode = S_IRUGO | S_IWUSR;
- priv->nvram_attr.read = rp5c01_nvram_read;
- priv->nvram_attr.write = rp5c01_nvram_write;
- priv->nvram_attr.size = RP5C01_MODE;
-
spin_lock_init(&priv->lock);
platform_set_drvdata(dev, priv);
- rtc = devm_rtc_device_register(&dev->dev, "rtc-rp5c01", &rp5c01_rtc_ops,
- THIS_MODULE);
+ rtc = devm_rtc_allocate_device(&dev->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
+
+ rtc->ops = &rp5c01_rtc_ops;
+ rtc->nvram_old_abi = true;
+
priv->rtc = rtc;
- error = sysfs_create_bin_file(&dev->dev.kobj, &priv->nvram_attr);
+ nvmem_cfg.priv = priv;
+ error = rtc_nvmem_register(rtc, &nvmem_cfg);
if (error)
return error;
- return 0;
-}
-
-static int __exit rp5c01_rtc_remove(struct platform_device *dev)
-{
- struct rp5c01_priv *priv = platform_get_drvdata(dev);
-
- sysfs_remove_bin_file(&dev->dev.kobj, &priv->nvram_attr);
- return 0;
+ return rtc_register_device(rtc);
}
static struct platform_driver rp5c01_rtc_driver = {
.driver = {
.name = "rtc-rp5c01",
},
- .remove = __exit_p(rp5c01_rtc_remove),
};
module_platform_driver_probe(rp5c01_rtc_driver, rp5c01_rtc_probe);
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c
index 9a306983aaba..f2de8b17e7e3 100644
--- a/drivers/rtc/rtc-rs5c348.c
+++ b/drivers/rtc/rtc-rs5c348.c
@@ -135,11 +135,6 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_year = bcd2bin(rxbuf[RS5C348_REG_YEAR]) +
((rxbuf[RS5C348_REG_MONTH] & RS5C348_BIT_Y2K) ? 100 : 0);
- if (rtc_valid_tm(tm) < 0) {
- dev_err(&spi->dev, "retrieved date/time is not valid.\n");
- rtc_time_to_tm(0, tm);
- }
-
return 0;
}
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index d4eff8d7131f..c5038329058c 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -207,8 +207,9 @@ static unsigned rs5c_hr2reg(struct rs5c372 *rs5c, unsigned hour)
return bin2bcd(hour);
}
-static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct rs5c372 *rs5c = i2c_get_clientdata(client);
int status = rs5c_get_regs(rs5c);
@@ -234,12 +235,12 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- /* rtc might need initialization */
- return rtc_valid_tm(tm);
+ return 0;
}
-static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct rs5c372 *rs5c = i2c_get_clientdata(client);
unsigned char buf[7];
int addr;
@@ -305,17 +306,6 @@ static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim)
}
#endif
-static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
- return rs5c372_get_datetime(to_i2c_client(dev), tm);
-}
-
-static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- return rs5c372_set_datetime(to_i2c_client(dev), tm);
-}
-
-
static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -581,7 +571,6 @@ static int rs5c372_probe(struct i2c_client *client,
int err = 0;
int smbus_mode = 0;
struct rs5c372 *rs5c372;
- struct rtc_time tm;
dev_dbg(&client->dev, "%s\n", __func__);
@@ -662,9 +651,6 @@ static int rs5c372_probe(struct i2c_client *client,
goto exit;
}
- if (rs5c372_get_datetime(client, &tm) < 0)
- dev_warn(&client->dev, "clock needs to be set\n");
-
dev_info(&client->dev, "%s found, %s\n",
({ char *s; switch (rs5c372->type) {
case rtc_r2025sd: s = "r2025sd"; break;
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index aae2576741a6..29fc3d210392 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -68,7 +68,6 @@ struct rv8803_data {
struct mutex flags_lock;
u8 ctrl;
enum rv8803_type type;
- struct nvmem_config nvmem_cfg;
};
static int rv8803_read_reg(const struct i2c_client *client, u8 reg)
@@ -528,6 +527,15 @@ static int rv8803_probe(struct i2c_client *client,
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct rv8803_data *rv8803;
int err, flags;
+ struct nvmem_config nvmem_cfg = {
+ .name = "rv8803_nvram",
+ .word_size = 1,
+ .stride = 1,
+ .size = 1,
+ .reg_read = rv8803_nvram_read,
+ .reg_write = rv8803_nvram_write,
+ .priv = client,
+ };
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK)) {
@@ -582,21 +590,6 @@ static int rv8803_probe(struct i2c_client *client,
}
}
- rv8803->nvmem_cfg.name = "rv8803_nvram",
- rv8803->nvmem_cfg.word_size = 1,
- rv8803->nvmem_cfg.stride = 1,
- rv8803->nvmem_cfg.size = 1,
- rv8803->nvmem_cfg.reg_read = rv8803_nvram_read,
- rv8803->nvmem_cfg.reg_write = rv8803_nvram_write,
- rv8803->nvmem_cfg.priv = client;
-
- rv8803->rtc->ops = &rv8803_rtc_ops;
- rv8803->rtc->nvmem_config = &rv8803->nvmem_cfg;
- rv8803->rtc->nvram_old_abi = true;
- err = rtc_register_device(rv8803->rtc);
- if (err)
- return err;
-
err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
if (err)
return err;
@@ -607,6 +600,14 @@ static int rv8803_probe(struct i2c_client *client,
return err;
}
+ rv8803->rtc->ops = &rv8803_rtc_ops;
+ rv8803->rtc->nvram_old_abi = true;
+ err = rtc_register_device(rv8803->rtc);
+ if (err)
+ return err;
+
+ rtc_nvmem_register(rv8803->rtc, &nvmem_cfg);
+
rv8803->rtc->max_user_freq = 1;
return 0;
diff --git a/drivers/rtc/rtc-rx4581.c b/drivers/rtc/rtc-rx4581.c
index de3fe4f8d133..c59a218bdd87 100644
--- a/drivers/rtc/rtc-rx4581.c
+++ b/drivers/rtc/rtc-rx4581.c
@@ -172,11 +172,7 @@ static int rx4581_get_datetime(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- err = rtc_valid_tm(tm);
- if (err < 0)
- dev_err(dev, "retrieved date/time is not valid.\n");
-
- return err;
+ return 0;
}
static int rx4581_set_datetime(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c
index 7c9c08eab5e5..8e322d884cc2 100644
--- a/drivers/rtc/rtc-rx6110.c
+++ b/drivers/rtc/rtc-rx6110.c
@@ -252,7 +252,7 @@ static int rx6110_get_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year);
- return rtc_valid_tm(tm);
+ return 0;
}
static const struct reg_sequence rx6110_default_regs[] = {
diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c
index 5c5938ab3d86..7ddc22eb5b0f 100644
--- a/drivers/rtc/rtc-rx8010.c
+++ b/drivers/rtc/rtc-rx8010.c
@@ -138,7 +138,7 @@ static int rx8010_get_time(struct device *dev, struct rtc_time *dt)
dt->tm_year = bcd2bin(date[RX8010_YEAR - RX8010_SEC]) + 100;
dt->tm_wday = ffs(date[RX8010_WDAY - RX8010_SEC] & 0x7f);
- return rtc_valid_tm(dt);
+ return 0;
}
static int rx8010_set_time(struct device *dev, struct rtc_time *dt)
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index 91857d8d2df8..41127adf5765 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -214,7 +214,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
dt->tm_sec, dt->tm_min, dt->tm_hour,
dt->tm_mday, dt->tm_mon, dt->tm_year);
- return rtc_valid_tm(dt);
+ return 0;
}
static int rx8025_set_time(struct device *dev, struct rtc_time *dt)
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c
index 9998d7937688..32caadf912ca 100644
--- a/drivers/rtc/rtc-rx8581.c
+++ b/drivers/rtc/rtc-rx8581.c
@@ -164,11 +164,7 @@ static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- err = rtc_valid_tm(tm);
- if (err < 0)
- dev_err(&client->dev, "retrieved date/time is not valid.\n");
-
- return err;
+ return 0;
}
static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index 7067bca5c20d..77feb603cd4c 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -210,8 +210,9 @@ static int s35390a_reg2hr(struct s35390a *s35390a, char reg)
return hour;
}
-static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client);
int i, err;
char buf[7], status;
@@ -241,8 +242,9 @@ static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return err;
}
-static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client);
char buf[7], status;
int i, err;
@@ -271,11 +273,12 @@ static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year,
tm->tm_wday);
- return rtc_valid_tm(tm);
+ return 0;
}
-static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
+static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client);
char buf[3], sts = 0;
int err, i;
@@ -329,8 +332,9 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
return err;
}
-static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
+static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client);
char buf[3], sts;
int i, err;
@@ -384,26 +388,6 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
return 0;
}
-static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
-{
- return s35390a_read_alarm(to_i2c_client(dev), alm);
-}
-
-static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
-{
- return s35390a_set_alarm(to_i2c_client(dev), alm);
-}
-
-static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
- return s35390a_get_datetime(to_i2c_client(dev), tm);
-}
-
-static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- return s35390a_set_datetime(to_i2c_client(dev), tm);
-}
-
static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd,
unsigned long arg)
{
@@ -450,7 +434,6 @@ static int s35390a_probe(struct i2c_client *client,
int err, err_read;
unsigned int i;
struct s35390a *s35390a;
- struct rtc_time tm;
char buf, status1;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
@@ -508,9 +491,6 @@ static int s35390a_probe(struct i2c_client *client,
}
}
- if (err_read > 0 || s35390a_get_datetime(client, &tm) < 0)
- dev_warn(&client->dev, "clock needs to be set\n");
-
device_set_wakeup_capable(&client->dev, 1);
s35390a->rtc = devm_rtc_device_register(&client->dev,
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index a8992c227f61..75c8c5033e08 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -232,7 +232,7 @@ retry_get_time:
rtc_tm->tm_mon -= 1;
- return rtc_valid_tm(rtc_tm);
+ return 0;
}
static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 0477678d968f..8428455432ca 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -38,6 +38,19 @@
*/
#define UDR_READ_RETRY_CNT 5
+enum {
+ RTC_SEC = 0,
+ RTC_MIN,
+ RTC_HOUR,
+ RTC_WEEKDAY,
+ RTC_DATE,
+ RTC_MONTH,
+ RTC_YEAR1,
+ RTC_YEAR2,
+ /* Make sure this is always the last enum name. */
+ RTC_MAX_NUM_TIME_REGS
+};
+
/*
* Registers used by the driver which are different between chipsets.
*
@@ -367,7 +380,7 @@ static void s5m8763_tm_to_data(struct rtc_time *tm, u8 *data)
static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct s5m_rtc_info *info = dev_get_drvdata(dev);
- u8 data[info->regs->regs_count];
+ u8 data[RTC_MAX_NUM_TIME_REGS];
int ret;
if (info->regs->read_time_udr_mask) {
@@ -407,13 +420,13 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday);
- return rtc_valid_tm(tm);
+ return 0;
}
static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct s5m_rtc_info *info = dev_get_drvdata(dev);
- u8 data[info->regs->regs_count];
+ u8 data[RTC_MAX_NUM_TIME_REGS];
int ret = 0;
switch (info->device_type) {
@@ -450,7 +463,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct s5m_rtc_info *info = dev_get_drvdata(dev);
- u8 data[info->regs->regs_count];
+ u8 data[RTC_MAX_NUM_TIME_REGS];
unsigned int val;
int ret, i;
@@ -500,7 +513,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
{
- u8 data[info->regs->regs_count];
+ u8 data[RTC_MAX_NUM_TIME_REGS];
int ret, i;
struct rtc_time tm;
@@ -545,7 +558,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
{
int ret;
- u8 data[info->regs->regs_count];
+ u8 data[RTC_MAX_NUM_TIME_REGS];
u8 alarm0_conf;
struct rtc_time tm;
@@ -598,7 +611,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct s5m_rtc_info *info = dev_get_drvdata(dev);
- u8 data[info->regs->regs_count];
+ u8 data[RTC_MAX_NUM_TIME_REGS];
int ret;
switch (info->device_type) {
diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c
index d544d5268757..00d87d138984 100644
--- a/drivers/rtc/rtc-sc27xx.c
+++ b/drivers/rtc/rtc-sc27xx.c
@@ -376,7 +376,7 @@ static int sprd_rtc_read_time(struct device *dev, struct rtc_time *tm)
return ret;
rtc_time64_to_tm(secs, tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int sprd_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 6c2d3989f967..4e8ab370ce63 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -414,7 +414,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
- return rtc_valid_tm(tm);
+ return 0;
}
static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c
index 7367f617145c..2a9e151cae99 100644
--- a/drivers/rtc/rtc-sirfsoc.c
+++ b/drivers/rtc/rtc-sirfsoc.c
@@ -204,23 +204,6 @@ static int sirfsoc_rtc_set_time(struct device *dev,
return 0;
}
-static int sirfsoc_rtc_ioctl(struct device *dev, unsigned int cmd,
- unsigned long arg)
-{
- switch (cmd) {
- case RTC_PIE_ON:
- case RTC_PIE_OFF:
- case RTC_UIE_ON:
- case RTC_UIE_OFF:
- case RTC_AIE_ON:
- case RTC_AIE_OFF:
- return 0;
-
- default:
- return -ENOIOCTLCMD;
- }
-}
-
static int sirfsoc_rtc_alarm_irq_enable(struct device *dev,
unsigned int enabled)
{
@@ -250,7 +233,6 @@ static const struct rtc_class_ops sirfsoc_rtc_ops = {
.set_time = sirfsoc_rtc_set_time,
.read_alarm = sirfsoc_rtc_read_alarm,
.set_alarm = sirfsoc_rtc_set_alarm,
- .ioctl = sirfsoc_rtc_ioctl,
.alarm_irq_enable = sirfsoc_rtc_alarm_irq_enable
};
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index d8ef9e052c4f..9af591d5223c 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -132,20 +132,23 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
unsigned long time;
+ int ret;
rtc_tm_to_time(tm, &time);
/* Disable RTC first */
- snvs_rtc_enable(data, false);
+ ret = snvs_rtc_enable(data, false);
+ if (ret)
+ return ret;
/* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
regmap_write(data->regmap, data->offset + SNVS_LPSRTCLR, time << CNTR_TO_SECS_SH);
regmap_write(data->regmap, data->offset + SNVS_LPSRTCMR, time >> (32 - CNTR_TO_SECS_SH));
/* Enable RTC again */
- snvs_rtc_enable(data, true);
+ ret = snvs_rtc_enable(data, true);
- return 0;
+ return ret;
}
static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@@ -288,7 +291,11 @@ static int snvs_rtc_probe(struct platform_device *pdev)
regmap_write(data->regmap, data->offset + SNVS_LPSR, 0xffffffff);
/* Enable RTC */
- snvs_rtc_enable(data, true);
+ ret = snvs_rtc_enable(data, true);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable rtc %d\n", ret);
+ goto error_rtc_device_register;
+ }
device_init_wakeup(&pdev->dev, true);
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c
index e377f42abae7..0567944fd4f8 100644
--- a/drivers/rtc/rtc-spear.c
+++ b/drivers/rtc/rtc-spear.c
@@ -170,18 +170,14 @@ static irqreturn_t spear_rtc_irq(int irq, void *dev_id)
}
-static int tm2bcd(struct rtc_time *tm)
+static void tm2bcd(struct rtc_time *tm)
{
- if (rtc_valid_tm(tm) != 0)
- return -EINVAL;
tm->tm_sec = bin2bcd(tm->tm_sec);
tm->tm_min = bin2bcd(tm->tm_min);
tm->tm_hour = bin2bcd(tm->tm_hour);
tm->tm_mday = bin2bcd(tm->tm_mday);
tm->tm_mon = bin2bcd(tm->tm_mon + 1);
tm->tm_year = bin2bcd(tm->tm_year);
-
- return 0;
}
static void bcd2tm(struct rtc_time *tm)
@@ -237,8 +233,7 @@ static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm)
struct spear_rtc_config *config = dev_get_drvdata(dev);
unsigned int time, date;
- if (tm2bcd(tm) < 0)
- return -EINVAL;
+ tm2bcd(tm);
rtc_wait_not_busy(config);
time = (tm->tm_sec << SECOND_SHIFT) | (tm->tm_min << MINUTE_SHIFT) |
@@ -295,8 +290,7 @@ static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
unsigned int time, date;
int err;
- if (tm2bcd(&alm->time) < 0)
- return -EINVAL;
+ tm2bcd(&alm->time);
rtc_wait_not_busy(config);
diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c
index 82b0af159a28..d5222667f892 100644
--- a/drivers/rtc/rtc-st-lpc.c
+++ b/drivers/rtc/rtc-st-lpc.c
@@ -195,7 +195,6 @@ static int st_rtc_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct st_rtc *rtc;
struct resource *res;
- struct rtc_time tm_check;
uint32_t mode;
int ret = 0;
@@ -254,21 +253,6 @@ static int st_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc);
- /*
- * The RTC-LPC is able to manage date.year > 2038
- * but currently the kernel can not manage this date!
- * If the RTC-LPC has a date.year > 2038 then
- * it's set to the epoch "Jan 1st 2000"
- */
- st_rtc_read_time(&pdev->dev, &tm_check);
-
- if (tm_check.tm_year >= (2038 - 1900)) {
- memset(&tm_check, 0, sizeof(tm_check));
- tm_check.tm_year = 100;
- tm_check.tm_mday = 1;
- st_rtc_set_time(&pdev->dev, &tm_check);
- }
-
rtc->rtc_dev = rtc_device_register("st-lpc-rtc", &pdev->dev,
&st_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc_dev)) {
diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c
index 7fc36973fa33..a7d49329d626 100644
--- a/drivers/rtc/rtc-starfire.c
+++ b/drivers/rtc/rtc-starfire.c
@@ -28,7 +28,7 @@ static u32 starfire_get_time(void)
static int starfire_read_time(struct device *dev, struct rtc_time *tm)
{
rtc_time_to_tm(starfire_get_time(), tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static const struct rtc_class_ops starfire_rtc_ops = {
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index a456cb6177ea..e70b78d17a98 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -129,10 +129,6 @@ static int stk17ta8_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* year is 1900 + tm->tm_year */
tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
- if (rtc_valid_tm(tm) < 0) {
- dev_err(dev, "retrieved date/time is not valid.\n");
- rtc_time_to_tm(0, tm);
- }
return 0;
}
@@ -242,46 +238,30 @@ static const struct rtc_class_ops stk17ta8_rtc_ops = {
.alarm_irq_enable = stk17ta8_rtc_alarm_irq_enable,
};
-static ssize_t stk17ta8_nvram_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
- loff_t pos, size_t size)
+static int stk17ta8_nvram_read(void *priv, unsigned int pos, void *val,
+ size_t bytes)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = priv;
void __iomem *ioaddr = pdata->ioaddr;
- ssize_t count;
+ u8 *buf = val;
- for (count = 0; count < size; count++)
+ for (; bytes; bytes--)
*buf++ = readb(ioaddr + pos++);
- return count;
+ return 0;
}
-static ssize_t stk17ta8_nvram_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
- loff_t pos, size_t size)
+static int stk17ta8_nvram_write(void *priv, unsigned int pos, void *val,
+ size_t bytes)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = priv;
void __iomem *ioaddr = pdata->ioaddr;
- ssize_t count;
+ u8 *buf = val;
- for (count = 0; count < size; count++)
+ for (; bytes; bytes--)
writeb(*buf++, ioaddr + pos++);
- return count;
+ return 0;
}
-static struct bin_attribute stk17ta8_nvram_attr = {
- .attr = {
- .name = "nvram",
- .mode = S_IRUGO | S_IWUSR,
- },
- .size = RTC_OFFSET,
- .read = stk17ta8_nvram_read,
- .write = stk17ta8_nvram_write,
-};
-
static int stk17ta8_rtc_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -290,6 +270,14 @@ static int stk17ta8_rtc_probe(struct platform_device *pdev)
struct rtc_plat_data *pdata;
void __iomem *ioaddr;
int ret = 0;
+ struct nvmem_config nvmem_cfg = {
+ .name = "stk17ta8_nvram",
+ .word_size = 1,
+ .stride = 1,
+ .size = RTC_OFFSET,
+ .reg_read = stk17ta8_nvram_read,
+ .reg_write = stk17ta8_nvram_write,
+ };
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -328,24 +316,19 @@ static int stk17ta8_rtc_probe(struct platform_device *pdev)
}
}
- pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
- &stk17ta8_rtc_ops, THIS_MODULE);
+ pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(pdata->rtc))
return PTR_ERR(pdata->rtc);
- ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr);
+ pdata->rtc->ops = &stk17ta8_rtc_ops;
+ pdata->rtc->nvram_old_abi = true;
- return ret;
-}
+ nvmem_cfg.priv = pdata;
+ ret = rtc_nvmem_register(pdata->rtc, &nvmem_cfg);
+ if (ret)
+ return ret;
-static int stk17ta8_rtc_remove(struct platform_device *pdev)
-{
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
- sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr);
- if (pdata->irq > 0)
- writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
- return 0;
+ return rtc_register_device(pdata->rtc);
}
/* work with hotplug and coldplug */
@@ -353,7 +336,6 @@ MODULE_ALIAS("platform:stk17ta8");
static struct platform_driver stk17ta8_rtc_driver = {
.probe = stk17ta8_rtc_probe,
- .remove = stk17ta8_rtc_remove,
.driver = {
.name = "stk17ta8",
},
diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index 5bc28eed1adf..2e6fb275acc8 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -349,7 +349,7 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
*/
rtc_tm->tm_year += SUN6I_YEAR_OFF;
- return rtc_valid_tm(rtc_tm);
+ return 0;
}
static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c
index abada609ddc7..dadbf8b324ad 100644
--- a/drivers/rtc/rtc-sunxi.c
+++ b/drivers/rtc/rtc-sunxi.c
@@ -261,7 +261,7 @@ static int sunxi_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
*/
rtc_tm->tm_year += SUNXI_YEAR_OFF(chip->data_year);
- return rtc_valid_tm(rtc_tm);
+ return 0;
}
static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 92ff2edb86a6..454da38c6012 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -248,6 +248,14 @@ offset_store(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RW(offset);
+static ssize_t
+range_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "[%lld,%llu]\n", to_rtc_device(dev)->range_min,
+ to_rtc_device(dev)->range_max);
+}
+static DEVICE_ATTR_RO(range);
+
static struct attribute *rtc_attrs[] = {
&dev_attr_name.attr,
&dev_attr_date.attr,
@@ -257,6 +265,7 @@ static struct attribute *rtc_attrs[] = {
&dev_attr_hctosys.attr,
&dev_attr_wakealarm.attr,
&dev_attr_offset.attr,
+ &dev_attr_range.attr,
NULL,
};
@@ -286,6 +295,9 @@ static umode_t rtc_attr_is_visible(struct kobject *kobj,
} else if (attr == &dev_attr_offset.attr) {
if (!rtc->ops->set_offset)
mode = 0;
+ } else if (attr == &dev_attr_range.attr) {
+ if (!(rtc->range_max - rtc->range_min))
+ mode = 0;
}
return mode;
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
index d30d57b048d3..66efff60c4d5 100644
--- a/drivers/rtc/rtc-tegra.c
+++ b/drivers/rtc/rtc-tegra.c
@@ -144,10 +144,6 @@ static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm)
int ret;
/* convert tm to seconds. */
- ret = rtc_valid_tm(tm);
- if (ret)
- return ret;
-
rtc_tm_to_time(tm, &sec);
dev_vdbg(dev, "time set to %lu. %d/%d/%d %d:%02u:%02u\n",
diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c
index a3418a8a3796..d7785ae0a2b4 100644
--- a/drivers/rtc/rtc-tps6586x.c
+++ b/drivers/rtc/rtc-tps6586x.c
@@ -90,7 +90,7 @@ static int tps6586x_rtc_read_time(struct device *dev, struct rtc_time *tm)
seconds = ticks >> 10;
seconds += rtc->epoch_start;
rtc_time_to_tm(seconds, tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int tps6586x_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c
index 560d9a5e0225..08dbefc79520 100644
--- a/drivers/rtc/rtc-tx4939.c
+++ b/drivers/rtc/rtc-tx4939.c
@@ -14,7 +14,30 @@
#include <linux/module.h>
#include <linux/io.h>
#include <linux/gfp.h>
-#include <asm/txx9/tx4939.h>
+
+#define TX4939_RTCCTL_ALME 0x00000080
+#define TX4939_RTCCTL_ALMD 0x00000040
+#define TX4939_RTCCTL_BUSY 0x00000020
+
+#define TX4939_RTCCTL_COMMAND 0x00000007
+#define TX4939_RTCCTL_COMMAND_NOP 0x00000000
+#define TX4939_RTCCTL_COMMAND_GETTIME 0x00000001
+#define TX4939_RTCCTL_COMMAND_SETTIME 0x00000002
+#define TX4939_RTCCTL_COMMAND_GETALARM 0x00000003
+#define TX4939_RTCCTL_COMMAND_SETALARM 0x00000004
+
+#define TX4939_RTCTBC_PM 0x00000080
+#define TX4939_RTCTBC_COMP 0x0000007f
+
+#define TX4939_RTC_REG_RAMSIZE 0x00000100
+#define TX4939_RTC_REG_RWBSIZE 0x00000006
+
+struct tx4939_rtc_reg {
+ __u32 ctl;
+ __u32 adr;
+ __u32 dat;
+ __u32 tbc;
+};
struct tx4939rtc_plat_data {
struct rtc_device *rtc;
@@ -86,9 +109,10 @@ static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm)
for (i = 2; i < 6; i++)
buf[i] = __raw_readl(&rtcreg->dat);
spin_unlock_irq(&pdata->lock);
- sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
+ sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) |
+ (buf[3] << 8) | buf[2];
rtc_time_to_tm(sec, tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int tx4939_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@@ -147,7 +171,8 @@ static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0;
alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0;
spin_unlock_irq(&pdata->lock);
- sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
+ sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) |
+ (buf[3] << 8) | buf[2];
rtc_time_to_tm(sec, &alrm->time);
return rtc_valid_tm(&alrm->time);
}
@@ -189,58 +214,52 @@ static const struct rtc_class_ops tx4939_rtc_ops = {
.alarm_irq_enable = tx4939_rtc_alarm_irq_enable,
};
-static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t size)
+static int tx4939_nvram_read(void *priv, unsigned int pos, void *val,
+ size_t bytes)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
+ struct tx4939rtc_plat_data *pdata = priv;
struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
- ssize_t count;
+ u8 *buf = val;
spin_lock_irq(&pdata->lock);
- for (count = 0; count < size; count++) {
+ for (; bytes; bytes--) {
__raw_writel(pos++, &rtcreg->adr);
*buf++ = __raw_readl(&rtcreg->dat);
}
spin_unlock_irq(&pdata->lock);
- return count;
+ return 0;
}
-static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t size)
+static int tx4939_nvram_write(void *priv, unsigned int pos, void *val,
+ size_t bytes)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
+ struct tx4939rtc_plat_data *pdata = priv;
struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
- ssize_t count;
+ u8 *buf = val;
spin_lock_irq(&pdata->lock);
- for (count = 0; count < size; count++) {
+ for (; bytes; bytes--) {
__raw_writel(pos++, &rtcreg->adr);
__raw_writel(*buf++, &rtcreg->dat);
}
spin_unlock_irq(&pdata->lock);
- return count;
+ return 0;
}
-static struct bin_attribute tx4939_rtc_nvram_attr = {
- .attr = {
- .name = "nvram",
- .mode = S_IRUGO | S_IWUSR,
- },
- .size = TX4939_RTC_REG_RAMSIZE,
- .read = tx4939_rtc_nvram_read,
- .write = tx4939_rtc_nvram_write,
-};
-
static int __init tx4939_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc;
struct tx4939rtc_plat_data *pdata;
struct resource *res;
int irq, ret;
+ struct nvmem_config nvmem_cfg = {
+ .name = "rv8803_nvram",
+ .word_size = 4,
+ .stride = 4,
+ .size = TX4939_RTC_REG_RAMSIZE,
+ .reg_read = tx4939_nvram_read,
+ .reg_write = tx4939_nvram_write,
+ };
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -260,21 +279,27 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev)
if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt,
0, pdev->name, &pdev->dev) < 0)
return -EBUSY;
- rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
- &tx4939_rtc_ops, THIS_MODULE);
+ rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
+
+ rtc->ops = &tx4939_rtc_ops;
+ rtc->nvram_old_abi = true;
+
pdata->rtc = rtc;
- ret = sysfs_create_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr);
- return ret;
+ nvmem_cfg.priv = pdata;
+ ret = rtc_nvmem_register(rtc, &nvmem_cfg);
+ if (ret)
+ return ret;
+
+ return rtc_register_device(rtc);
}
static int __exit tx4939_rtc_remove(struct platform_device *pdev)
{
struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev);
- sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr);
spin_lock_irq(&pdata->lock);
tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
spin_unlock_irq(&pdata->lock);
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c
index 75aea4c4d334..7b824dabf104 100644
--- a/drivers/rtc/rtc-wm831x.c
+++ b/drivers/rtc/rtc-wm831x.c
@@ -156,7 +156,7 @@ static int wm831x_rtc_readtime(struct device *dev, struct rtc_time *tm)
u32 time = (time1[0] << 16) | time1[1];
rtc_time_to_tm(time, tm);
- return rtc_valid_tm(tm);
+ return 0;
}
} while (++count < WM831X_GET_TIME_RETRIES);
diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c
index 0c34d3b81279..153820876a82 100644
--- a/drivers/rtc/rtc-xgene.c
+++ b/drivers/rtc/rtc-xgene.c
@@ -60,7 +60,7 @@ static int xgene_rtc_read_time(struct device *dev, struct rtc_time *tm)
struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
rtc_time_to_tm(readl(pdata->csr_base + RTC_CCVR), tm);
- return rtc_valid_tm(tm);
+ return 0;
}
static int xgene_rtc_set_mmss(struct device *dev, unsigned long secs)
diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
index da18a8ae3c1d..fba994dc31eb 100644
--- a/drivers/rtc/rtc-zynqmp.c
+++ b/drivers/rtc/rtc-zynqmp.c
@@ -122,7 +122,7 @@ static int xlnx_rtc_read_time(struct device *dev, struct rtc_time *tm)
rtc_time64_to_tm(read_time, tm);
}
- return rtc_valid_tm(tm);
+ return 0;
}
static int xlnx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
diff --git a/drivers/rtc/systohc.c b/drivers/rtc/systohc.c
index 0c177647ea6c..718293d72426 100644
--- a/drivers/rtc/systohc.c
+++ b/drivers/rtc/systohc.c
@@ -20,7 +20,7 @@
* cases.
*
* -EPROTO is returned if now.tv_nsec is not close enough to *target_nsec.
- (
+ *
* If temporary failure is indicated the caller should try again 'soon'
*/
int rtc_set_ntp_time(struct timespec64 now, unsigned long *target_nsec)
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index 1444333210c7..9ac7574e3cfb 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -15,8 +15,8 @@ config BLK_DEV_XPRAM
config DCSSBLK
def_tristate m
- select DAX
select FS_DAX_LIMITED
+ select DAX_DRIVER
prompt "DCSSBLK support"
depends on S390 && BLOCK
help
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index a993d19fa562..5c4535b545cc 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -37,7 +37,7 @@ config QCOM_PM
config QCOM_QMI_HELPERS
tristate
- depends on ARCH_QCOM
+ depends on ARCH_QCOM && NET
help
Helper library for handling QMI encoded messages. QMI encoded
messages are used in communication between the majority of QRTR
diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 08bd8549242a..17b314d9a148 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -83,12 +83,14 @@ EXPORT_SYMBOL_GPL(qcom_mdt_get_size);
* @mem_region: allocated memory region to load firmware into
* @mem_phys: physical address of allocated memory region
* @mem_size: size of the allocated memory region
+ * @reloc_base: adjusted physical address after relocation
*
* Returns 0 on success, negative errno otherwise.
*/
int qcom_mdt_load(struct device *dev, const struct firmware *fw,
const char *firmware, int pas_id, void *mem_region,
- phys_addr_t mem_phys, size_t mem_size)
+ phys_addr_t mem_phys, size_t mem_size,
+ phys_addr_t *reloc_base)
{
const struct elf32_phdr *phdrs;
const struct elf32_phdr *phdr;
@@ -192,6 +194,9 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw,
memset(ptr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
}
+ if (reloc_base)
+ *reloc_base = mem_reloc;
+
out:
kfree(fw_name);
diff --git a/drivers/staging/lustre/lustre/llite/glimpse.c b/drivers/staging/lustre/lustre/llite/glimpse.c
index c43ac574274c..3075358f3f08 100644
--- a/drivers/staging/lustre/lustre/llite/glimpse.c
+++ b/drivers/staging/lustre/lustre/llite/glimpse.c
@@ -69,7 +69,7 @@ blkcnt_t dirty_cnt(struct inode *inode)
void *results[1];
if (inode->i_mapping)
- cnt += radix_tree_gang_lookup_tag(&inode->i_mapping->page_tree,
+ cnt += radix_tree_gang_lookup_tag(&inode->i_mapping->i_pages,
results, 0, 1,
PAGECACHE_TAG_DIRTY);
if (cnt == 0 && atomic_read(&vob->vob_mmap_cnt) > 0)
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c
index 3b1c8e5a3053..8ee7b4d273b2 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_request.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c
@@ -934,14 +934,14 @@ static struct page *mdc_page_locate(struct address_space *mapping, __u64 *hash,
struct page *page;
int found;
- spin_lock_irq(&mapping->tree_lock);
- found = radix_tree_gang_lookup(&mapping->page_tree,
+ xa_lock_irq(&mapping->i_pages);
+ found = radix_tree_gang_lookup(&mapping->i_pages,
(void **)&page, offset, 1);
if (found > 0 && !radix_tree_exceptional_entry(page)) {
struct lu_dirpage *dp;
get_page(page);
- spin_unlock_irq(&mapping->tree_lock);
+ xa_unlock_irq(&mapping->i_pages);
/*
* In contrast to find_lock_page() we are sure that directory
* page cannot be truncated (while DLM lock is held) and,
@@ -989,7 +989,7 @@ static struct page *mdc_page_locate(struct address_space *mapping, __u64 *hash,
page = ERR_PTR(-EIO);
}
} else {
- spin_unlock_irq(&mapping->tree_lock);
+ xa_unlock_irq(&mapping->i_pages);
page = NULL;
}
return page;
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
index 93753cb96180..512fa87fa11b 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c
@@ -619,7 +619,7 @@ static const struct v4l2_ctrl_ops ctrl_ops = {
.g_volatile_ctrl = gc0310_g_volatile_ctrl
};
-struct v4l2_ctrl_config gc0310_controls[] = {
+static const struct v4l2_ctrl_config gc0310_controls[] = {
{
.ops = &ctrl_ops,
.id = V4L2_CID_EXPOSURE_ABSOLUTE,
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
index 834fba8c4fa0..44db9f9f1fc5 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c
@@ -107,7 +107,7 @@ mt9m114_write_reg(struct i2c_client *client, u16 data_length, u16 reg, u32 val)
int num_msg;
struct i2c_msg msg;
unsigned char data[6] = {0};
- u16 *wreg;
+ __be16 *wreg;
int retry = 0;
if (!client->adapter) {
@@ -130,18 +130,20 @@ again:
msg.buf = data;
/* high byte goes out first */
- wreg = (u16 *)data;
+ wreg = (void *)data;
*wreg = cpu_to_be16(reg);
if (data_length == MISENSOR_8BIT) {
data[2] = (u8)(val);
} else if (data_length == MISENSOR_16BIT) {
- u16 *wdata = (u16 *)&data[2];
- *wdata = be16_to_cpu((u16)val);
+ u16 *wdata = (void *)&data[2];
+
+ *wdata = be16_to_cpu(*(__be16 *)&data[2]);
} else {
/* MISENSOR_32BIT */
- u32 *wdata = (u32 *)&data[2];
- *wdata = be32_to_cpu(val);
+ u32 *wdata = (void *)&data[2];
+
+ *wdata = be32_to_cpu(*(__be32 *)&data[2]);
}
num_msg = i2c_transfer(client->adapter, &msg, 1);
@@ -245,6 +247,7 @@ static int __mt9m114_flush_reg_array(struct i2c_client *client,
const int num_msg = 1;
int ret;
int retry = 0;
+ __be16 *data16 = (void *)&ctrl->buffer.addr;
if (ctrl->index == 0)
return 0;
@@ -253,7 +256,7 @@ again:
msg.addr = client->addr;
msg.flags = 0;
msg.len = 2 + ctrl->index;
- ctrl->buffer.addr = cpu_to_be16(ctrl->buffer.addr);
+ *data16 = cpu_to_be16(ctrl->buffer.addr);
msg.buf = (u8 *)&ctrl->buffer;
ret = i2c_transfer(client->adapter, &msg, num_msg);
@@ -282,8 +285,8 @@ static int __mt9m114_buf_reg_array(struct i2c_client *client,
struct mt9m114_write_ctrl *ctrl,
const struct misensor_reg *next)
{
- u16 *data16;
- u32 *data32;
+ __be16 *data16;
+ __be32 *data32;
int err;
/* Insufficient buffer? Let's flush and get more free space. */
@@ -298,11 +301,11 @@ static int __mt9m114_buf_reg_array(struct i2c_client *client,
ctrl->buffer.data[ctrl->index] = (u8)next->val;
break;
case MISENSOR_16BIT:
- data16 = (u16 *)&ctrl->buffer.data[ctrl->index];
+ data16 = (__be16 *)&ctrl->buffer.data[ctrl->index];
*data16 = cpu_to_be16((u16)next->val);
break;
case MISENSOR_32BIT:
- data32 = (u32 *)&ctrl->buffer.data[ctrl->index];
+ data32 = (__be32 *)&ctrl->buffer.data[ctrl->index];
*data32 = cpu_to_be32(next->val);
break;
default:
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
index 11412061c40e..c0849299d592 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
@@ -94,9 +94,9 @@ static int ov2680_read_reg(struct i2c_client *client,
if (data_length == OV2680_8BIT)
*val = (u8)data[0];
else if (data_length == OV2680_16BIT)
- *val = be16_to_cpu(*(u16 *)&data[0]);
+ *val = be16_to_cpu(*(__be16 *)&data[0]);
else
- *val = be32_to_cpu(*(u32 *)&data[0]);
+ *val = be32_to_cpu(*(__be32 *)&data[0]);
//dev_dbg(&client->dev, "++++i2c read adr%x = %x\n", reg,*val);
return 0;
}
@@ -121,7 +121,7 @@ static int ov2680_write_reg(struct i2c_client *client, u16 data_length,
{
int ret;
unsigned char data[4] = {0};
- u16 *wreg = (u16 *)data;
+ __be16 *wreg = (void *)data;
const u16 len = data_length + sizeof(u16); /* 16-bit address + data */
if (data_length != OV2680_8BIT && data_length != OV2680_16BIT) {
@@ -137,7 +137,8 @@ static int ov2680_write_reg(struct i2c_client *client, u16 data_length,
data[2] = (u8)(val);
} else {
/* OV2680_16BIT */
- u16 *wdata = (u16 *)&data[2];
+ __be16 *wdata = (void *)&data[2];
+
*wdata = cpu_to_be16(val);
}
@@ -169,12 +170,13 @@ static int __ov2680_flush_reg_array(struct i2c_client *client,
struct ov2680_write_ctrl *ctrl)
{
u16 size;
+ __be16 *data16 = (void *)&ctrl->buffer.addr;
if (ctrl->index == 0)
return 0;
size = sizeof(u16) + ctrl->index; /* 16-bit address + data */
- ctrl->buffer.addr = cpu_to_be16(ctrl->buffer.addr);
+ *data16 = cpu_to_be16(ctrl->buffer.addr);
ctrl->index = 0;
return ov2680_i2c_write(client, size, (u8 *)&ctrl->buffer);
@@ -185,7 +187,7 @@ static int __ov2680_buf_reg_array(struct i2c_client *client,
const struct ov2680_reg *next)
{
int size;
- u16 *data16;
+ __be16 *data16;
switch (next->type) {
case OV2680_8BIT:
@@ -194,7 +196,7 @@ static int __ov2680_buf_reg_array(struct i2c_client *client,
break;
case OV2680_16BIT:
size = 2;
- data16 = (u16 *)&ctrl->buffer.data[ctrl->index];
+ data16 = (void *)&ctrl->buffer.data[ctrl->index];
*data16 = cpu_to_be16((u16)next->val);
break;
default:
@@ -722,7 +724,7 @@ static const struct v4l2_ctrl_ops ctrl_ops = {
.g_volatile_ctrl = ov2680_g_volatile_ctrl
};
-struct v4l2_ctrl_config ov2680_controls[] = {
+static const struct v4l2_ctrl_config ov2680_controls[] = {
{
.ops = &ctrl_ops,
.id = V4L2_CID_EXPOSURE_ABSOLUTE,
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c
index e59358ac89ce..a362eebd882f 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c
@@ -85,9 +85,9 @@ static int ov2722_read_reg(struct i2c_client *client,
if (data_length == OV2722_8BIT)
*val = (u8)data[0];
else if (data_length == OV2722_16BIT)
- *val = be16_to_cpu(*(u16 *)&data[0]);
+ *val = be16_to_cpu(*(__be16 *)&data[0]);
else
- *val = be32_to_cpu(*(u32 *)&data[0]);
+ *val = be32_to_cpu(*(__be32 *)&data[0]);
return 0;
}
@@ -112,7 +112,7 @@ static int ov2722_write_reg(struct i2c_client *client, u16 data_length,
{
int ret;
unsigned char data[4] = {0};
- u16 *wreg = (u16 *)data;
+ __be16 *wreg = (__be16 *)data;
const u16 len = data_length + sizeof(u16); /* 16-bit address + data */
if (data_length != OV2722_8BIT && data_length != OV2722_16BIT) {
@@ -128,7 +128,8 @@ static int ov2722_write_reg(struct i2c_client *client, u16 data_length,
data[2] = (u8)(val);
} else {
/* OV2722_16BIT */
- u16 *wdata = (u16 *)&data[2];
+ __be16 *wdata = (__be16 *)&data[2];
+
*wdata = cpu_to_be16(val);
}
@@ -160,12 +161,13 @@ static int __ov2722_flush_reg_array(struct i2c_client *client,
struct ov2722_write_ctrl *ctrl)
{
u16 size;
+ __be16 *data16 = (void *)&ctrl->buffer.addr;
if (ctrl->index == 0)
return 0;
size = sizeof(u16) + ctrl->index; /* 16-bit address + data */
- ctrl->buffer.addr = cpu_to_be16(ctrl->buffer.addr);
+ *data16 = cpu_to_be16(ctrl->buffer.addr);
ctrl->index = 0;
return ov2722_i2c_write(client, size, (u8 *)&ctrl->buffer);
@@ -176,7 +178,7 @@ static int __ov2722_buf_reg_array(struct i2c_client *client,
const struct ov2722_reg *next)
{
int size;
- u16 *data16;
+ __be16 *data16;
switch (next->type) {
case OV2722_8BIT:
@@ -185,7 +187,7 @@ static int __ov2722_buf_reg_array(struct i2c_client *client,
break;
case OV2722_16BIT:
size = 2;
- data16 = (u16 *)&ctrl->buffer.data[ctrl->index];
+ data16 = (void *)&ctrl->buffer.data[ctrl->index];
*data16 = cpu_to_be16((u16)next->val);
break;
default:
@@ -569,7 +571,7 @@ static const struct v4l2_ctrl_ops ctrl_ops = {
.g_volatile_ctrl = ov2722_g_volatile_ctrl
};
-struct v4l2_ctrl_config ov2722_controls[] = {
+static const struct v4l2_ctrl_config ov2722_controls[] = {
{
.ops = &ctrl_ops,
.id = V4L2_CID_EXPOSURE_ABSOLUTE,
diff --git a/drivers/staging/media/atomisp/i2c/gc0310.h b/drivers/staging/media/atomisp/i2c/gc0310.h
index af6b11f6e5e7..70c252c5163c 100644
--- a/drivers/staging/media/atomisp/i2c/gc0310.h
+++ b/drivers/staging/media/atomisp/i2c/gc0310.h
@@ -377,8 +377,7 @@ static struct gc0310_reg const gc0310_VGA_30fps[] = {
{GC0310_TOK_TERM, 0, 0},
};
-
-struct gc0310_resolution gc0310_res_preview[] = {
+static struct gc0310_resolution gc0310_res_preview[] = {
{
.desc = "gc0310_VGA_30fps",
.width = 656, // 648,
diff --git a/drivers/staging/media/atomisp/i2c/ov2722.h b/drivers/staging/media/atomisp/i2c/ov2722.h
index 028b04aaaa8f..757b37613ccc 100644
--- a/drivers/staging/media/atomisp/i2c/ov2722.h
+++ b/drivers/staging/media/atomisp/i2c/ov2722.h
@@ -1096,7 +1096,7 @@ static struct ov2722_reg const ov2722_720p_30fps[] = {
{OV2722_TOK_TERM, 0, 0},
};
-struct ov2722_resolution ov2722_res_preview[] = {
+static struct ov2722_resolution ov2722_res_preview[] = {
{
.desc = "ov2722_1632_1092_30fps",
.width = 1632,
diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
index 30a735e59e54..714297c36b3e 100644
--- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
+++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
@@ -173,9 +173,9 @@ static int ov5693_read_reg(struct i2c_client *client,
if (data_length == OV5693_8BIT)
*val = (u8)data[0];
else if (data_length == OV5693_16BIT)
- *val = be16_to_cpu(*(u16 *)&data[0]);
+ *val = be16_to_cpu(*(__be16 *)&data[0]);
else
- *val = be32_to_cpu(*(u32 *)&data[0]);
+ *val = be32_to_cpu(*(__be32 *)&data[0]);
return 0;
}
@@ -200,13 +200,13 @@ static int vcm_dw_i2c_write(struct i2c_client *client, u16 data)
struct i2c_msg msg;
const int num_msg = 1;
int ret;
- u16 val;
+ __be16 val;
val = cpu_to_be16(data);
msg.addr = VCM_ADDR;
msg.flags = 0;
msg.len = OV5693_16BIT;
- msg.buf = (u8 *)&val;
+ msg.buf = (void *)&val;
ret = i2c_transfer(client->adapter, &msg, 1);
@@ -263,7 +263,7 @@ static int ov5693_write_reg(struct i2c_client *client, u16 data_length,
{
int ret;
unsigned char data[4] = {0};
- u16 *wreg = (u16 *)data;
+ __be16 *wreg = (void *)data;
const u16 len = data_length + sizeof(u16); /* 16-bit address + data */
if (data_length != OV5693_8BIT && data_length != OV5693_16BIT) {
@@ -279,7 +279,8 @@ static int ov5693_write_reg(struct i2c_client *client, u16 data_length,
data[2] = (u8)(val);
} else {
/* OV5693_16BIT */
- u16 *wdata = (u16 *)&data[2];
+ __be16 *wdata = (void *)&data[2];
+
*wdata = cpu_to_be16(val);
}
@@ -311,15 +312,17 @@ static int __ov5693_flush_reg_array(struct i2c_client *client,
struct ov5693_write_ctrl *ctrl)
{
u16 size;
+ __be16 *reg = (void *)&ctrl->buffer.addr;
if (ctrl->index == 0)
return 0;
size = sizeof(u16) + ctrl->index; /* 16-bit address + data */
- ctrl->buffer.addr = cpu_to_be16(ctrl->buffer.addr);
+
+ *reg = cpu_to_be16(ctrl->buffer.addr);
ctrl->index = 0;
- return ov5693_i2c_write(client, size, (u8 *)&ctrl->buffer);
+ return ov5693_i2c_write(client, size, (u8 *)reg);
}
static int __ov5693_buf_reg_array(struct i2c_client *client,
@@ -327,7 +330,7 @@ static int __ov5693_buf_reg_array(struct i2c_client *client,
const struct ov5693_reg *next)
{
int size;
- u16 *data16;
+ __be16 *data16;
switch (next->type) {
case OV5693_8BIT:
@@ -336,7 +339,8 @@ static int __ov5693_buf_reg_array(struct i2c_client *client,
break;
case OV5693_16BIT:
size = 2;
- data16 = (u16 *)&ctrl->buffer.data[ctrl->index];
+
+ data16 = (void *)&ctrl->buffer.data[ctrl->index];
*data16 = cpu_to_be16((u16)next->val);
break;
default:
@@ -951,7 +955,7 @@ static int ad5823_t_focus_vcm(struct v4l2_subdev *sd, u16 val)
return ret;
}
-int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+static int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value)
{
value = min(value, AD5823_MAX_FOCUS_POS);
return ad5823_t_focus_vcm(sd, value);
@@ -1132,7 +1136,7 @@ static const struct v4l2_ctrl_ops ctrl_ops = {
.g_volatile_ctrl = ov5693_g_volatile_ctrl
};
-struct v4l2_ctrl_config ov5693_controls[] = {
+static const struct v4l2_ctrl_config ov5693_controls[] = {
{
.ops = &ctrl_ops,
.id = V4L2_CID_EXPOSURE_ABSOLUTE,
diff --git a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
index 6d27dd849a62..9058a82455a6 100644
--- a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
+++ b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
@@ -1087,7 +1087,7 @@ static struct ov5693_reg const ov5693_2576x1936_30fps[] = {
{OV5693_TOK_TERM, 0, 0}
};
-struct ov5693_resolution ov5693_res_preview[] = {
+static struct ov5693_resolution ov5693_res_preview[] = {
{
.desc = "ov5693_736x496_30fps",
.width = 736,
diff --git a/drivers/staging/media/atomisp/include/linux/atomisp_platform.h b/drivers/staging/media/atomisp/include/linux/atomisp_platform.h
index e0f0c379e7ce..aa5e294e7b7d 100644
--- a/drivers/staging/media/atomisp/include/linux/atomisp_platform.h
+++ b/drivers/staging/media/atomisp/include/linux/atomisp_platform.h
@@ -104,6 +104,10 @@ enum atomisp_input_format {
ATOMISP_INPUT_FORMAT_USER_DEF8, /* User defined 8-bit data type 8 */
};
+#define N_ATOMISP_INPUT_FORMAT (ATOMISP_INPUT_FORMAT_USER_DEF8 + 1)
+
+
+
enum intel_v4l2_subdev_type {
RAW_CAMERA = 1,
SOC_CAMERA = 2,
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/Makefile b/drivers/staging/media/atomisp/pci/atomisp2/Makefile
index 83f816faba1b..7fead5fc9a7d 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/Makefile
+++ b/drivers/staging/media/atomisp/pci/atomisp2/Makefile
@@ -59,17 +59,14 @@ atomisp-objs += \
css2400/isp/kernels/bnr/bnr_1.0/ia_css_bnr.host.o \
css2400/isp/kernels/bnr/bnr2_2/ia_css_bnr2_2.host.o \
css2400/isp/kernels/dpc2/ia_css_dpc2.host.o \
- css2400/isp/kernels/dpc2/ia_css_dpc2_default.host.o \
css2400/isp/kernels/fc/fc_1.0/ia_css_formats.host.o \
css2400/isp/kernels/ctc/ctc_1.0/ia_css_ctc.host.o \
css2400/isp/kernels/ctc/ctc_1.0/ia_css_ctc_table.host.o \
css2400/isp/kernels/ctc/ctc2/ia_css_ctc2.host.o \
css2400/isp/kernels/ctc/ctc1_5/ia_css_ctc1_5.host.o \
css2400/isp/kernels/bh/bh_2/ia_css_bh.host.o \
- css2400/isp/kernels/bnlm/ia_css_bnlm_default.host.o \
css2400/isp/kernels/bnlm/ia_css_bnlm.host.o \
css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.o \
- css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf_default.host.o \
css2400/isp/kernels/dvs/dvs_1.0/ia_css_dvs.host.o \
css2400/isp/kernels/anr/anr_1.0/ia_css_anr.host.o \
css2400/isp/kernels/anr/anr_2/ia_css_anr2_table.host.o \
@@ -96,7 +93,6 @@ atomisp-objs += \
css2400/isp/kernels/ob/ob2/ia_css_ob2.host.o \
css2400/isp/kernels/iterator/iterator_1.0/ia_css_iterator.host.o \
css2400/isp/kernels/wb/wb_1.0/ia_css_wb.host.o \
- css2400/isp/kernels/eed1_8/ia_css_eed1_8_default.host.o \
css2400/isp/kernels/eed1_8/ia_css_eed1_8.host.o \
css2400/isp/kernels/sc/sc_1.0/ia_css_sc.host.o \
css2400/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.o \
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_cmd.c
index 22f2dbcecc15..fa6ea506f8b1 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_cmd.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_cmd.c
@@ -437,7 +437,7 @@ static void atomisp_reset_event(struct atomisp_sub_device *asd)
}
-static void print_csi_rx_errors(enum ia_css_csi2_port port,
+static void print_csi_rx_errors(enum mipi_port_id port,
struct atomisp_device *isp)
{
u32 infos = 0;
@@ -481,7 +481,7 @@ static void clear_irq_reg(struct atomisp_device *isp)
}
static struct atomisp_sub_device *
-__get_asd_from_port(struct atomisp_device *isp, mipi_port_ID_t port)
+__get_asd_from_port(struct atomisp_device *isp, enum mipi_port_id port)
{
int i;
@@ -515,7 +515,7 @@ irqreturn_t atomisp_isr(int irq, void *dev)
spin_lock_irqsave(&isp->lock, flags);
if (isp->sw_contex.power_state != ATOM_ISP_POWER_UP ||
- isp->css_initialized == false) {
+ !isp->css_initialized) {
spin_unlock_irqrestore(&isp->lock, flags);
return IRQ_HANDLED;
}
@@ -570,9 +570,9 @@ irqreturn_t atomisp_isr(int irq, void *dev)
(irq_infos & CSS_IRQ_INFO_IF_ERROR)) {
/* handle mipi receiver error */
u32 rx_infos;
- enum ia_css_csi2_port port;
+ enum mipi_port_id port;
- for (port = IA_CSS_CSI2_PORT0; port <= IA_CSS_CSI2_PORT2;
+ for (port = MIPI_PORT0_ID; port <= MIPI_PORT2_ID;
port++) {
print_csi_rx_errors(port, isp);
atomisp_css_rx_get_irq_info(port, &rx_infos);
@@ -4603,7 +4603,7 @@ int atomisp_fixed_pattern(struct atomisp_sub_device *asd, int flag,
}
if (*value == 0) {
- asd->params.fpn_en = 0;
+ asd->params.fpn_en = false;
return 0;
}
@@ -5028,7 +5028,7 @@ atomisp_try_fmt_file(struct atomisp_device *isp, struct v4l2_format *f)
return 0;
}
-mipi_port_ID_t __get_mipi_port(struct atomisp_device *isp,
+enum mipi_port_id __get_mipi_port(struct atomisp_device *isp,
enum atomisp_camera_port port)
{
switch (port) {
@@ -5162,22 +5162,22 @@ static int __enable_continuous_mode(struct atomisp_sub_device *asd,
return atomisp_update_run_mode(asd);
}
-int configure_pp_input_nop(struct atomisp_sub_device *asd,
- unsigned int width, unsigned int height)
+static int configure_pp_input_nop(struct atomisp_sub_device *asd,
+ unsigned int width, unsigned int height)
{
return 0;
}
-int configure_output_nop(struct atomisp_sub_device *asd,
- unsigned int width, unsigned int height,
- unsigned int min_width,
- enum atomisp_css_frame_format sh_fmt)
+static int configure_output_nop(struct atomisp_sub_device *asd,
+ unsigned int width, unsigned int height,
+ unsigned int min_width,
+ enum atomisp_css_frame_format sh_fmt)
{
return 0;
}
-int get_frame_info_nop(struct atomisp_sub_device *asd,
- struct atomisp_css_frame_info *finfo)
+static int get_frame_info_nop(struct atomisp_sub_device *asd,
+ struct atomisp_css_frame_info *finfo)
{
return 0;
}
@@ -5524,7 +5524,7 @@ static void atomisp_get_dis_envelop(struct atomisp_sub_device *asd,
/* if subdev type is SOC camera,we do not need to set DVS */
if (isp->inputs[asd->input_curr].type == SOC_CAMERA)
- asd->params.video_dis_en = 0;
+ asd->params.video_dis_en = false;
if (asd->params.video_dis_en &&
asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
@@ -5624,7 +5624,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev,
ffmt = req_ffmt;
dev_warn(isp->dev,
"can not enable video dis due to sensor limitation.");
- asd->params.video_dis_en = 0;
+ asd->params.video_dis_en = false;
}
}
dev_dbg(isp->dev, "sensor width: %d, height: %d\n",
@@ -5649,7 +5649,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev,
(ffmt->width < req_ffmt->width || ffmt->height < req_ffmt->height)) {
dev_warn(isp->dev,
"can not enable video dis due to sensor limitation.");
- asd->params.video_dis_en = 0;
+ asd->params.video_dis_en = false;
}
atomisp_subdev_set_ffmt(&asd->subdev, fh.pad,
@@ -6152,7 +6152,7 @@ int atomisp_set_shading_table(struct atomisp_sub_device *asd,
if (!user_shading_table->enable) {
atomisp_css_set_shading_table(asd, NULL);
- asd->params.sc_en = 0;
+ asd->params.sc_en = false;
return 0;
}
@@ -6190,7 +6190,7 @@ int atomisp_set_shading_table(struct atomisp_sub_device *asd,
free_table = asd->params.css_param.shading_table;
asd->params.css_param.shading_table = shading_table;
atomisp_css_set_shading_table(asd, shading_table);
- asd->params.sc_en = 1;
+ asd->params.sc_en = true;
out:
if (free_table != NULL)
@@ -6627,7 +6627,7 @@ int atomisp_inject_a_fake_event(struct atomisp_sub_device *asd, int *event)
return 0;
}
-int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe)
+static int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe)
{
struct atomisp_sub_device *asd = pipe->asd;
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_cmd.h
index bdc73862fb79..79d493dba403 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_cmd.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_cmd.h
@@ -389,7 +389,7 @@ int atomisp_source_pad_to_stream_id(struct atomisp_sub_device *asd,
*/
void atomisp_eof_event(struct atomisp_sub_device *asd, uint8_t exp_id);
-mipi_port_ID_t __get_mipi_port(struct atomisp_device *isp,
+enum mipi_port_id __get_mipi_port(struct atomisp_device *isp,
enum atomisp_camera_port port);
bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat.h
index 3ef850cd25bd..6c829d0a1e4c 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat.h
@@ -148,10 +148,10 @@ void atomisp_css_init_struct(struct atomisp_sub_device *asd);
int atomisp_css_irq_translate(struct atomisp_device *isp,
unsigned int *infos);
-void atomisp_css_rx_get_irq_info(enum ia_css_csi2_port port,
+void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
unsigned int *infos);
-void atomisp_css_rx_clear_irq_info(enum ia_css_csi2_port port,
+void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
unsigned int infos);
int atomisp_css_irq_enable(struct atomisp_device *isp,
@@ -182,8 +182,6 @@ void atomisp_css_mmu_invalidate_cache(void);
void atomisp_css_mmu_invalidate_tlb(void);
-void atomisp_css_mmu_set_page_table_base_index(unsigned long base_index);
-
int atomisp_css_start(struct atomisp_sub_device *asd,
enum atomisp_css_pipe_id pipe_id, bool in_reset);
@@ -255,7 +253,7 @@ void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
- enum atomisp_css_stream_format format,
+ enum atomisp_input_format format,
int isys_stream);
int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
@@ -264,18 +262,18 @@ int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
- enum atomisp_css_stream_format input_format);
+ enum atomisp_input_format input_format);
void atomisp_css_isys_two_stream_cfg_update_stream1(
struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
- enum atomisp_css_stream_format input_format,
+ enum atomisp_input_format input_format,
unsigned int width, unsigned int height);
void atomisp_css_isys_two_stream_cfg_update_stream2(
struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
- enum atomisp_css_stream_format input_format,
+ enum atomisp_input_format input_format,
unsigned int width, unsigned int height);
int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
@@ -292,7 +290,7 @@ void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
- enum atomisp_css_stream_format format);
+ enum atomisp_input_format format);
int atomisp_css_input_set_effective_resolution(
struct atomisp_sub_device *asd,
@@ -334,11 +332,11 @@ void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
bool enable);
int atomisp_css_input_configure_port(struct atomisp_sub_device *asd,
- mipi_port_ID_t port,
+ enum mipi_port_id port,
unsigned int num_lanes,
unsigned int timeout,
unsigned int mipi_freq,
- enum atomisp_css_stream_format metadata_format,
+ enum atomisp_input_format metadata_format,
unsigned int metadata_width,
unsigned int metadata_height);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c
index 7621b4537147..f668c68dc33a 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c
@@ -88,7 +88,7 @@ unsigned int atomisp_css_debug_get_dtrace_level(void)
return ia_css_debug_trace_level;
}
-void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
+static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
{
unsigned long flags;
@@ -126,7 +126,7 @@ static uint8_t atomisp_css2_hw_load_8(hrt_address addr)
return ret;
}
-uint16_t atomisp_css2_hw_load_16(hrt_address addr)
+static uint16_t atomisp_css2_hw_load_16(hrt_address addr)
{
unsigned long flags;
uint16_t ret;
@@ -136,7 +136,8 @@ uint16_t atomisp_css2_hw_load_16(hrt_address addr)
spin_unlock_irqrestore(&mmio_lock, flags);
return ret;
}
-uint32_t atomisp_css2_hw_load_32(hrt_address addr)
+
+static uint32_t atomisp_css2_hw_load_32(hrt_address addr)
{
unsigned long flags;
uint32_t ret;
@@ -1019,7 +1020,7 @@ int atomisp_css_irq_translate(struct atomisp_device *isp,
return 0;
}
-void atomisp_css_rx_get_irq_info(enum ia_css_csi2_port port,
+void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
unsigned int *infos)
{
#ifndef ISP2401_NEW_INPUT_SYSTEM
@@ -1029,7 +1030,7 @@ void atomisp_css_rx_get_irq_info(enum ia_css_csi2_port port,
#endif
}
-void atomisp_css_rx_clear_irq_info(enum ia_css_csi2_port port,
+void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
unsigned int infos)
{
#ifndef ISP2401_NEW_INPUT_SYSTEM
@@ -1159,31 +1160,6 @@ void atomisp_css_mmu_invalidate_tlb(void)
ia_css_mmu_invalidate_cache();
}
-void atomisp_css_mmu_set_page_table_base_index(unsigned long base_index)
-{
-}
-
-/*
- * Check whether currently running MIPI buffer size fulfill
- * the requirement of the stream to be run
- */
-bool __need_realloc_mipi_buffer(struct atomisp_device *isp)
-{
- unsigned int i;
-
- for (i = 0; i < isp->num_of_streams; i++) {
- struct atomisp_sub_device *asd = &isp->asd[i];
-
- if (asd->streaming !=
- ATOMISP_DEVICE_STREAMING_ENABLED)
- continue;
- if (asd->mipi_frame_size < isp->mipi_frame_size)
- return true;
- }
-
- return false;
-}
-
int atomisp_css_start(struct atomisp_sub_device *asd,
enum atomisp_css_pipe_id pipe_id, bool in_reset)
{
@@ -1808,7 +1784,7 @@ void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
- enum atomisp_css_stream_format format,
+ enum atomisp_input_format format,
int isys_stream)
{
@@ -1820,7 +1796,7 @@ void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
- enum atomisp_css_stream_format format)
+ enum atomisp_input_format format)
{
struct ia_css_stream_config *s_config =
@@ -1859,7 +1835,7 @@ int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
- enum atomisp_css_stream_format input_format)
+ enum atomisp_input_format input_format)
{
struct ia_css_stream_config *s_config =
&asd->stream_env[stream_id].stream_config;
@@ -1873,9 +1849,9 @@ int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
= IA_CSS_STREAM_ISYS_STREAM_0;
s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
- IA_CSS_STREAM_FORMAT_USER_DEF1;
+ ATOMISP_INPUT_FORMAT_USER_DEF1;
s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
- IA_CSS_STREAM_FORMAT_USER_DEF2;
+ ATOMISP_INPUT_FORMAT_USER_DEF2;
s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
return 0;
}
@@ -1883,7 +1859,7 @@ int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
void atomisp_css_isys_two_stream_cfg_update_stream1(
struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
- enum atomisp_css_stream_format input_format,
+ enum atomisp_input_format input_format,
unsigned int width, unsigned int height)
{
struct ia_css_stream_config *s_config =
@@ -1901,7 +1877,7 @@ void atomisp_css_isys_two_stream_cfg_update_stream1(
void atomisp_css_isys_two_stream_cfg_update_stream2(
struct atomisp_sub_device *asd,
enum atomisp_input_stream_id stream_id,
- enum atomisp_css_stream_format input_format,
+ enum atomisp_input_format input_format,
unsigned int width, unsigned int height)
{
struct ia_css_stream_config *s_config =
@@ -2142,11 +2118,11 @@ void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
int atomisp_css_input_configure_port(
struct atomisp_sub_device *asd,
- mipi_port_ID_t port,
+ enum mipi_port_id port,
unsigned int num_lanes,
unsigned int timeout,
unsigned int mipi_freq,
- enum atomisp_css_stream_format metadata_format,
+ enum atomisp_input_format metadata_format,
unsigned int metadata_width,
unsigned int metadata_height)
{
@@ -2890,8 +2866,8 @@ stream_err:
return -EINVAL;
}
-unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
- uint16_t source_pad)
+static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
+ uint16_t source_pad)
{
struct atomisp_device *isp = asd->isp;
/*
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.h b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.h
index b03711668eda..a06c5b6e8027 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.h
@@ -37,7 +37,6 @@
#define atomisp_css_irq_info ia_css_irq_info
#define atomisp_css_isp_config ia_css_isp_config
#define atomisp_css_bayer_order ia_css_bayer_order
-#define atomisp_css_stream_format ia_css_stream_format
#define atomisp_css_capture_mode ia_css_capture_mode
#define atomisp_css_input_mode ia_css_input_mode
#define atomisp_css_frame ia_css_frame
@@ -117,7 +116,7 @@
*/
#define CSS_ID(val) (IA_ ## val)
#define CSS_EVENT(val) (IA_CSS_EVENT_TYPE_ ## val)
-#define CSS_FORMAT(val) (IA_CSS_STREAM_FORMAT_ ## val)
+#define CSS_FORMAT(val) (ATOMISP_INPUT_FORMAT_ ## val)
#define CSS_EVENT_PORT_EOF CSS_EVENT(PORT_EOF)
#define CSS_EVENT_FRAME_TAGGED CSS_EVENT(FRAME_TAGGED)
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_drvfs.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_drvfs.c
index ceedb82b6beb..a815c768bda9 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_drvfs.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_drvfs.c
@@ -22,6 +22,7 @@
#include "atomisp_compat.h"
#include "atomisp_internal.h"
#include "atomisp_ioctl.h"
+#include "atomisp_drvfs.h"
#include "hmm/hmm.h"
/*
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c
index 545ef024841d..709137f25700 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_fops.c
@@ -689,7 +689,7 @@ static void atomisp_dev_init_struct(struct atomisp_device *isp)
{
unsigned int i;
- isp->sw_contex.file_input = 0;
+ isp->sw_contex.file_input = false;
isp->need_gfx_throttle = true;
isp->isp_fatal_error = false;
isp->mipi_frame_size = 0;
@@ -708,12 +708,12 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd)
v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_STILL_CAPTURE);
memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
asd->params.color_effect = V4L2_COLORFX_NONE;
- asd->params.bad_pixel_en = 1;
- asd->params.gdc_cac_en = 0;
- asd->params.video_dis_en = 0;
- asd->params.sc_en = 0;
- asd->params.fpn_en = 0;
- asd->params.xnr_en = 0;
+ asd->params.bad_pixel_en = true;
+ asd->params.gdc_cac_en = false;
+ asd->params.video_dis_en = false;
+ asd->params.sc_en = false;
+ asd->params.fpn_en = false;
+ asd->params.xnr_en = false;
asd->params.false_color = 0;
asd->params.online_process = 1;
asd->params.yuv_ds_en = 0;
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_ioctl.c
index 5c84dd63778e..61bd550dafb9 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_ioctl.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_ioctl.c
@@ -1607,10 +1607,12 @@ int atomisp_stream_on_master_slave_sensor(struct atomisp_device *isp,
/* FIXME! */
#ifndef ISP2401
-void __wdt_on_master_slave_sensor(struct atomisp_device *isp, unsigned int wdt_duration)
+static void __wdt_on_master_slave_sensor(struct atomisp_device *isp,
+ unsigned int wdt_duration)
#else
-void __wdt_on_master_slave_sensor(struct atomisp_video_pipe *pipe,
- unsigned int wdt_duration, bool enable)
+static void __wdt_on_master_slave_sensor(struct atomisp_video_pipe *pipe,
+ unsigned int wdt_duration,
+ bool enable)
#endif
{
#ifndef ISP2401
@@ -2731,7 +2733,7 @@ static int atomisp_s_parm_file(struct file *file, void *fh,
}
rt_mutex_lock(&isp->mutex);
- isp->sw_contex.file_input = 1;
+ isp->sw_contex.file_input = true;
rt_mutex_unlock(&isp->mutex);
return 0;
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c
index b78276ac22da..49a9973b4289 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.c
@@ -42,17 +42,17 @@ const struct atomisp_in_fmt_conv atomisp_in_fmt_conv[] = {
{ MEDIA_BUS_FMT_SGBRG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, CSS_BAYER_ORDER_GBRG, CSS_FORMAT_RAW_12 },
{ MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, CSS_BAYER_ORDER_GRBG, CSS_FORMAT_RAW_12 },
{ MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, CSS_BAYER_ORDER_RGGB, CSS_FORMAT_RAW_12 },
- { MEDIA_BUS_FMT_UYVY8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0, IA_CSS_STREAM_FORMAT_YUV422_8 },
- { MEDIA_BUS_FMT_YUYV8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0, IA_CSS_STREAM_FORMAT_YUV422_8 },
- { MEDIA_BUS_FMT_JPEG_1X8, 8, 8, CSS_FRAME_FORMAT_BINARY_8, 0, IA_CSS_STREAM_FORMAT_BINARY_8 },
+ { MEDIA_BUS_FMT_UYVY8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0, ATOMISP_INPUT_FORMAT_YUV422_8 },
+ { MEDIA_BUS_FMT_YUYV8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0, ATOMISP_INPUT_FORMAT_YUV422_8 },
+ { MEDIA_BUS_FMT_JPEG_1X8, 8, 8, CSS_FRAME_FORMAT_BINARY_8, 0, ATOMISP_INPUT_FORMAT_BINARY_8 },
{ V4L2_MBUS_FMT_CUSTOM_NV12, 12, 12, CSS_FRAME_FORMAT_NV12, 0, CSS_FRAME_FORMAT_NV12 },
{ V4L2_MBUS_FMT_CUSTOM_NV21, 12, 12, CSS_FRAME_FORMAT_NV21, 0, CSS_FRAME_FORMAT_NV21 },
- { V4L2_MBUS_FMT_CUSTOM_YUV420, 12, 12, ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY, 0, IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY },
+ { V4L2_MBUS_FMT_CUSTOM_YUV420, 12, 12, ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY, 0, ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY },
#if 0
- { V4L2_MBUS_FMT_CUSTOM_M10MO_RAW, 8, 8, CSS_FRAME_FORMAT_BINARY_8, 0, IA_CSS_STREAM_FORMAT_BINARY_8 },
+ { V4L2_MBUS_FMT_CUSTOM_M10MO_RAW, 8, 8, CSS_FRAME_FORMAT_BINARY_8, 0, ATOMISP_INPUT_FORMAT_BINARY_8 },
#endif
/* no valid V4L2 MBUS code for metadata format, so leave it 0. */
- { 0, 0, 0, ATOMISP_INPUT_FORMAT_EMBEDDED, 0, IA_CSS_STREAM_FORMAT_EMBEDDED },
+ { 0, 0, 0, ATOMISP_INPUT_FORMAT_EMBEDDED, 0, ATOMISP_INPUT_FORMAT_EMBEDDED },
{}
};
@@ -101,7 +101,7 @@ const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv(u32 code)
}
const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_by_atomisp_in_fmt(
- enum atomisp_css_stream_format atomisp_in_fmt)
+ enum atomisp_input_format atomisp_in_fmt)
{
int i;
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.h
index c3eba675da06..59ff8723c182 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_subdev.h
@@ -58,9 +58,9 @@ struct atomisp_in_fmt_conv {
u32 code;
uint8_t bpp; /* bits per pixel */
uint8_t depth; /* uncompressed */
- enum atomisp_css_stream_format atomisp_in_fmt;
+ enum atomisp_input_format atomisp_in_fmt;
enum atomisp_css_bayer_order bayer_order;
- enum ia_css_stream_format css_stream_fmt;
+ enum atomisp_input_format css_stream_fmt;
};
struct atomisp_sub_device;
@@ -424,10 +424,10 @@ bool atomisp_subdev_is_compressed(u32 code);
const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv(u32 code);
#ifndef ISP2401
const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_by_atomisp_in_fmt(
- enum atomisp_css_stream_format atomisp_in_fmt);
+ enum atomisp_input_format atomisp_in_fmt);
#else
const struct atomisp_in_fmt_conv
- *atomisp_find_in_fmt_conv_by_atomisp_in_fmt(enum atomisp_css_stream_format
+ *atomisp_find_in_fmt_conv_by_atomisp_in_fmt(enum atomisp_input_format
atomisp_in_fmt);
#endif
const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_compressed(u32 code);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/camera/util/interface/ia_css_util.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/camera/util/interface/ia_css_util.h
index a8c27676a38b..5ab48f346790 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/camera/util/interface/ia_css_util.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/camera/util/interface/ia_css_util.h
@@ -116,7 +116,7 @@ extern bool ia_css_util_resolution_is_even(
*
*/
extern unsigned int ia_css_util_input_format_bpp(
- enum ia_css_stream_format stream_format,
+ enum atomisp_input_format stream_format,
bool two_ppc);
/* @brief check if input format it raw
@@ -126,7 +126,7 @@ extern unsigned int ia_css_util_input_format_bpp(
*
*/
extern bool ia_css_util_is_input_format_raw(
- enum ia_css_stream_format stream_format);
+ enum atomisp_input_format stream_format);
/* @brief check if input format it yuv
*
@@ -135,7 +135,7 @@ extern bool ia_css_util_is_input_format_raw(
*
*/
extern bool ia_css_util_is_input_format_yuv(
- enum ia_css_stream_format stream_format);
+ enum atomisp_input_format stream_format);
#endif /* __IA_CSS_UTIL_H__ */
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/camera/util/src/util.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/camera/util/src/util.c
index 54193789a809..91e586112332 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/camera/util/src/util.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/camera/util/src/util.c
@@ -52,55 +52,55 @@ enum ia_css_err ia_css_convert_errno(
/* MW: Table look-up ??? */
unsigned int ia_css_util_input_format_bpp(
- enum ia_css_stream_format format,
+ enum atomisp_input_format format,
bool two_ppc)
{
unsigned int rval = 0;
switch (format) {
- case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
- case IA_CSS_STREAM_FORMAT_YUV420_8:
- case IA_CSS_STREAM_FORMAT_YUV422_8:
- case IA_CSS_STREAM_FORMAT_RGB_888:
- case IA_CSS_STREAM_FORMAT_RAW_8:
- case IA_CSS_STREAM_FORMAT_BINARY_8:
- case IA_CSS_STREAM_FORMAT_EMBEDDED:
+ case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
+ case ATOMISP_INPUT_FORMAT_YUV420_8:
+ case ATOMISP_INPUT_FORMAT_YUV422_8:
+ case ATOMISP_INPUT_FORMAT_RGB_888:
+ case ATOMISP_INPUT_FORMAT_RAW_8:
+ case ATOMISP_INPUT_FORMAT_BINARY_8:
+ case ATOMISP_INPUT_FORMAT_EMBEDDED:
rval = 8;
break;
- case IA_CSS_STREAM_FORMAT_YUV420_10:
- case IA_CSS_STREAM_FORMAT_YUV422_10:
- case IA_CSS_STREAM_FORMAT_RAW_10:
+ case ATOMISP_INPUT_FORMAT_YUV420_10:
+ case ATOMISP_INPUT_FORMAT_YUV422_10:
+ case ATOMISP_INPUT_FORMAT_RAW_10:
rval = 10;
break;
- case IA_CSS_STREAM_FORMAT_YUV420_16:
- case IA_CSS_STREAM_FORMAT_YUV422_16:
+ case ATOMISP_INPUT_FORMAT_YUV420_16:
+ case ATOMISP_INPUT_FORMAT_YUV422_16:
rval = 16;
break;
- case IA_CSS_STREAM_FORMAT_RGB_444:
+ case ATOMISP_INPUT_FORMAT_RGB_444:
rval = 4;
break;
- case IA_CSS_STREAM_FORMAT_RGB_555:
+ case ATOMISP_INPUT_FORMAT_RGB_555:
rval = 5;
break;
- case IA_CSS_STREAM_FORMAT_RGB_565:
+ case ATOMISP_INPUT_FORMAT_RGB_565:
rval = 65;
break;
- case IA_CSS_STREAM_FORMAT_RGB_666:
- case IA_CSS_STREAM_FORMAT_RAW_6:
+ case ATOMISP_INPUT_FORMAT_RGB_666:
+ case ATOMISP_INPUT_FORMAT_RAW_6:
rval = 6;
break;
- case IA_CSS_STREAM_FORMAT_RAW_7:
+ case ATOMISP_INPUT_FORMAT_RAW_7:
rval = 7;
break;
- case IA_CSS_STREAM_FORMAT_RAW_12:
+ case ATOMISP_INPUT_FORMAT_RAW_12:
rval = 12;
break;
- case IA_CSS_STREAM_FORMAT_RAW_14:
+ case ATOMISP_INPUT_FORMAT_RAW_14:
if (two_ppc)
rval = 14;
else
rval = 12;
break;
- case IA_CSS_STREAM_FORMAT_RAW_16:
+ case ATOMISP_INPUT_FORMAT_RAW_16:
if (two_ppc)
rval = 16;
else
@@ -175,28 +175,28 @@ bool ia_css_util_resolution_is_even(const struct ia_css_resolution resolution)
}
#endif
-bool ia_css_util_is_input_format_raw(enum ia_css_stream_format format)
+bool ia_css_util_is_input_format_raw(enum atomisp_input_format format)
{
- return ((format == IA_CSS_STREAM_FORMAT_RAW_6) ||
- (format == IA_CSS_STREAM_FORMAT_RAW_7) ||
- (format == IA_CSS_STREAM_FORMAT_RAW_8) ||
- (format == IA_CSS_STREAM_FORMAT_RAW_10) ||
- (format == IA_CSS_STREAM_FORMAT_RAW_12));
+ return ((format == ATOMISP_INPUT_FORMAT_RAW_6) ||
+ (format == ATOMISP_INPUT_FORMAT_RAW_7) ||
+ (format == ATOMISP_INPUT_FORMAT_RAW_8) ||
+ (format == ATOMISP_INPUT_FORMAT_RAW_10) ||
+ (format == ATOMISP_INPUT_FORMAT_RAW_12));
/* raw_14 and raw_16 are not supported as input formats to the ISP.
* They can only be copied to a frame in memory using the
* copy binary.
*/
}
-bool ia_css_util_is_input_format_yuv(enum ia_css_stream_format format)
+bool ia_css_util_is_input_format_yuv(enum atomisp_input_format format)
{
- return format == IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY ||
- format == IA_CSS_STREAM_FORMAT_YUV420_8 ||
- format == IA_CSS_STREAM_FORMAT_YUV420_10 ||
- format == IA_CSS_STREAM_FORMAT_YUV420_16 ||
- format == IA_CSS_STREAM_FORMAT_YUV422_8 ||
- format == IA_CSS_STREAM_FORMAT_YUV422_10 ||
- format == IA_CSS_STREAM_FORMAT_YUV422_16;
+ return format == ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY ||
+ format == ATOMISP_INPUT_FORMAT_YUV420_8 ||
+ format == ATOMISP_INPUT_FORMAT_YUV420_10 ||
+ format == ATOMISP_INPUT_FORMAT_YUV420_16 ||
+ format == ATOMISP_INPUT_FORMAT_YUV422_8 ||
+ format == ATOMISP_INPUT_FORMAT_YUV422_10 ||
+ format == ATOMISP_INPUT_FORMAT_YUV422_16;
}
enum ia_css_err ia_css_util_check_input(
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/css_2401_csi2p_system/system_global.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/css_2401_csi2p_system/system_global.h
index d2e3a2deea2e..7907f0ff6d6c 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/css_2401_csi2p_system/system_global.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/css_2401_csi2p_system/system_global.h
@@ -284,12 +284,12 @@ typedef enum {
N_RX_ID
} rx_ID_t;
-typedef enum {
+enum mipi_port_id {
MIPI_PORT0_ID = 0,
MIPI_PORT1_ID,
MIPI_PORT2_ID,
N_MIPI_PORT_ID
-} mipi_port_ID_t;
+};
#define N_RX_CHANNEL_ID 4
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/debug.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/debug.c
index c412810887b3..dcb9a3127cfe 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/debug.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/debug.c
@@ -29,7 +29,7 @@
hrt_address debug_buffer_address = (hrt_address)-1;
hrt_vaddress debug_buffer_ddr_address = (hrt_vaddress)-1;
/* The local copy */
-debug_data_t debug_data;
+static debug_data_t debug_data;
debug_data_t *debug_data_ptr = &debug_data;
void debug_buffer_init(const hrt_address addr)
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/gp_timer.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/gp_timer.c
index bcfd443f5202..b6b1344786b1 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/gp_timer.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/gp_timer.c
@@ -29,7 +29,7 @@ gp_timer_reg_load(uint32_t reg);
static void
gp_timer_reg_store(uint32_t reg, uint32_t value);
-uint32_t
+static uint32_t
gp_timer_reg_load(uint32_t reg)
{
return ia_css_device_load_uint32(
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_formatter.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_formatter.c
index a8997e45738e..0e1ca995fb06 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_formatter.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_formatter.c
@@ -45,8 +45,9 @@ const uint8_t HIVE_IF_SWITCH_CODE[N_INPUT_FORMATTER_ID] = {
HIVE_INPUT_SWITCH_SELECT_STR_TO_MEM};
/* MW Should be part of system_global.h, where we have the main enumeration */
-const bool HIVE_IF_BIN_COPY[N_INPUT_FORMATTER_ID] = {
- false, false, false, true};
+static const bool HIVE_IF_BIN_COPY[N_INPUT_FORMATTER_ID] = {
+ false, false, false, true
+};
void input_formatter_rst(
const input_formatter_ID_t ID)
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system.c
index bd6821e436b2..2515e162828f 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system.c
@@ -29,7 +29,7 @@
#define ZERO (0x0)
#define ONE (1U)
-const ib_buffer_t IB_BUFFER_NULL = {0 ,0, 0 };
+static const ib_buffer_t IB_BUFFER_NULL = {0 ,0, 0 };
static input_system_error_t input_system_configure_channel(
const channel_cfg_t channel);
@@ -98,7 +98,7 @@ static inline void ctrl_unit_get_state(
static inline void mipi_port_get_state(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
mipi_port_state_t *state);
static inline void rx_channel_get_state(
@@ -180,7 +180,7 @@ void receiver_get_state(
const rx_ID_t ID,
receiver_state_t *state)
{
- mipi_port_ID_t port_id;
+ enum mipi_port_id port_id;
unsigned int ch_id;
assert(ID < N_RX_ID);
@@ -209,7 +209,7 @@ void receiver_get_state(
state->raw16 = (uint16_t)receiver_reg_load(ID,
_HRT_CSS_RECEIVER_RAW16_REG_IDX);
- for (port_id = (mipi_port_ID_t)0; port_id < N_MIPI_PORT_ID; port_id++) {
+ for (port_id = (enum mipi_port_id)0; port_id < N_MIPI_PORT_ID; port_id++) {
mipi_port_get_state(ID, port_id,
&(state->mipi_port_state[port_id]));
}
@@ -305,7 +305,7 @@ void receiver_set_compression(
void receiver_port_enable(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
const bool cnd)
{
hrt_data reg = receiver_port_reg_load(ID, port_ID,
@@ -324,7 +324,7 @@ void receiver_port_enable(
bool is_receiver_port_enabled(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID)
+ const enum mipi_port_id port_ID)
{
hrt_data reg = receiver_port_reg_load(ID, port_ID,
_HRT_CSS_RECEIVER_DEVICE_READY_REG_IDX);
@@ -333,7 +333,7 @@ bool is_receiver_port_enabled(
void receiver_irq_enable(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
const rx_irq_info_t irq_info)
{
receiver_port_reg_store(ID,
@@ -343,7 +343,7 @@ void receiver_irq_enable(
rx_irq_info_t receiver_get_irq_info(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID)
+ const enum mipi_port_id port_ID)
{
return receiver_port_reg_load(ID,
port_ID, _HRT_CSS_RECEIVER_IRQ_STATUS_REG_IDX);
@@ -351,7 +351,7 @@ rx_irq_info_t receiver_get_irq_info(
void receiver_irq_clear(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
const rx_irq_info_t irq_info)
{
receiver_port_reg_store(ID,
@@ -556,7 +556,7 @@ static inline void ctrl_unit_get_state(
static inline void mipi_port_get_state(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
mipi_port_state_t *state)
{
int i;
@@ -644,12 +644,12 @@ static inline void rx_channel_get_state(
}
// MW: "2400" in the name is not good, but this is to avoid a naming conflict
-input_system_cfg2400_t config;
+static input_system_cfg2400_t config;
static void receiver_rst(
const rx_ID_t ID)
{
- mipi_port_ID_t port_id;
+ enum mipi_port_id port_id;
assert(ID < N_RX_ID);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system_local.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system_local.h
index 3e8bd00082dc..bf9230fd08f2 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system_local.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system_local.h
@@ -353,7 +353,7 @@ typedef struct rx_cfg_s rx_cfg_t;
*/
struct rx_cfg_s {
rx_mode_t mode; /* The HW config */
- mipi_port_ID_t port; /* The port ID to apply the control on */
+ enum mipi_port_id port; /* The port ID to apply the control on */
unsigned int timeout;
unsigned int initcount;
unsigned int synccount;
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system_private.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system_private.h
index 118185eb86e9..48876bb08b70 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system_private.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/input_system_private.h
@@ -63,7 +63,7 @@ STORAGE_CLASS_INPUT_SYSTEM_C hrt_data receiver_reg_load(
STORAGE_CLASS_INPUT_SYSTEM_C void receiver_port_reg_store(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
const hrt_address reg,
const hrt_data value)
{
@@ -77,7 +77,7 @@ STORAGE_CLASS_INPUT_SYSTEM_C void receiver_port_reg_store(
STORAGE_CLASS_INPUT_SYSTEM_C hrt_data receiver_port_reg_load(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
const hrt_address reg)
{
assert(ID < N_RX_ID);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/system_global.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/system_global.h
index d803efd7400a..6f63962a54e8 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/system_global.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/system_global.h
@@ -266,12 +266,12 @@ typedef enum {
N_RX_ID
} rx_ID_t;
-typedef enum {
+enum mipi_port_id {
MIPI_PORT0_ID = 0,
MIPI_PORT1_ID,
MIPI_PORT2_ID,
N_MIPI_PORT_ID
-} mipi_port_ID_t;
+};
#define N_RX_CHANNEL_ID 4
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/host/input_system_public.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/host/input_system_public.h
index 1596757fe9ef..6e37ff0fe0f9 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/host/input_system_public.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_include/host/input_system_public.h
@@ -83,7 +83,7 @@ extern void receiver_set_compression(
*/
extern void receiver_port_enable(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
const bool cnd);
/*! Flag if PORT[port_ID] of RECEIVER[ID] is enabled
@@ -95,7 +95,7 @@ extern void receiver_port_enable(
*/
extern bool is_receiver_port_enabled(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID);
+ const enum mipi_port_id port_ID);
/*! Enable the IRQ channels of PORT[port_ID] of RECEIVER[ID]
@@ -107,7 +107,7 @@ extern bool is_receiver_port_enabled(
*/
extern void receiver_irq_enable(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
const rx_irq_info_t irq_info);
/*! Return the IRQ status of PORT[port_ID] of RECEIVER[ID]
@@ -119,7 +119,7 @@ extern void receiver_irq_enable(
*/
extern rx_irq_info_t receiver_get_irq_info(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID);
+ const enum mipi_port_id port_ID);
/*! Clear the IRQ status of PORT[port_ID] of RECEIVER[ID]
@@ -131,7 +131,7 @@ extern rx_irq_info_t receiver_get_irq_info(
*/
extern void receiver_irq_clear(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
const rx_irq_info_t irq_info);
/*! Write to a control register of INPUT_SYSTEM[ID]
@@ -195,7 +195,7 @@ STORAGE_CLASS_INPUT_SYSTEM_H hrt_data receiver_reg_load(
*/
STORAGE_CLASS_INPUT_SYSTEM_H void receiver_port_reg_store(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
const hrt_address reg,
const hrt_data value);
@@ -210,7 +210,7 @@ STORAGE_CLASS_INPUT_SYSTEM_H void receiver_port_reg_store(
*/
STORAGE_CLASS_INPUT_SYSTEM_H hrt_data receiver_port_reg_load(
const rx_ID_t ID,
- const mipi_port_ID_t port_ID,
+ const enum mipi_port_id port_ID,
const hrt_address reg);
/*! Write to a control register of SUB_SYSTEM[sub_ID] of INPUT_SYSTEM[ID]
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_input_port.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_input_port.h
index f415570a3da9..ad9ca5449369 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_input_port.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_input_port.h
@@ -12,6 +12,9 @@
* more details.
*/
+/* For MIPI_PORT0_ID to MIPI_PORT2_ID */
+#include "system_global.h"
+
#ifndef __IA_CSS_INPUT_PORT_H
#define __IA_CSS_INPUT_PORT_H
@@ -19,21 +22,12 @@
* This file contains information about the possible input ports for CSS
*/
-/* Enumeration of the physical input ports on the CSS hardware.
- * There are 3 MIPI CSI-2 ports.
- */
-enum ia_css_csi2_port {
- IA_CSS_CSI2_PORT0, /* Implicitly map to MIPI_PORT0_ID */
- IA_CSS_CSI2_PORT1, /* Implicitly map to MIPI_PORT1_ID */
- IA_CSS_CSI2_PORT2 /* Implicitly map to MIPI_PORT2_ID */
-};
-
/* Backward compatible for CSS API 2.0 only
* TO BE REMOVED when all drivers move to CSS API 2.1
*/
-#define IA_CSS_CSI2_PORT_4LANE IA_CSS_CSI2_PORT0
-#define IA_CSS_CSI2_PORT_1LANE IA_CSS_CSI2_PORT1
-#define IA_CSS_CSI2_PORT_2LANE IA_CSS_CSI2_PORT2
+#define IA_CSS_CSI2_PORT_4LANE MIPI_PORT0_ID
+#define IA_CSS_CSI2_PORT_1LANE MIPI_PORT1_ID
+#define IA_CSS_CSI2_PORT_2LANE MIPI_PORT2_ID
/* The CSI2 interface supports 2 types of compression or can
* be run without compression.
@@ -56,7 +50,7 @@ struct ia_css_csi2_compression {
/* Input port structure.
*/
struct ia_css_input_port {
- enum ia_css_csi2_port port; /** Physical CSI-2 port */
+ enum mipi_port_id port; /** Physical CSI-2 port */
unsigned int num_lanes; /** Number of lanes used (4-lane port only) */
unsigned int timeout; /** Timeout value */
unsigned int rxcount; /** Register value, should include all lanes */
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_irq.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_irq.h
index 10ef61178bb2..c8840138899a 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_irq.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_irq.h
@@ -186,7 +186,7 @@ ia_css_rx_get_irq_info(unsigned int *irq_bits);
* that occurred.
*/
void
-ia_css_rx_port_get_irq_info(enum ia_css_csi2_port port, unsigned int *irq_bits);
+ia_css_rx_port_get_irq_info(enum mipi_port_id port, unsigned int *irq_bits);
/* @brief Clear CSI receiver error info.
*
@@ -218,7 +218,7 @@ ia_css_rx_clear_irq_info(unsigned int irq_bits);
* error bits get overwritten.
*/
void
-ia_css_rx_port_clear_irq_info(enum ia_css_csi2_port port, unsigned int irq_bits);
+ia_css_rx_port_clear_irq_info(enum mipi_port_id port, unsigned int irq_bits);
/* @brief Enable or disable specific interrupts.
*
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_metadata.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_metadata.h
index 8b674c98224c..ed0b6ab371da 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_metadata.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_metadata.h
@@ -27,8 +27,8 @@
* to process sensor metadata.
*/
struct ia_css_metadata_config {
- enum ia_css_stream_format data_type; /** Data type of CSI-2 embedded
- data. The default value is IA_CSS_STREAM_FORMAT_EMBEDDED. For
+ enum atomisp_input_format data_type; /** Data type of CSI-2 embedded
+ data. The default value is ATOMISP_INPUT_FORMAT_EMBEDDED. For
certain sensors, user can choose non-default data type for embedded
data. */
struct ia_css_resolution resolution; /** Resolution */
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_mipi.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_mipi.h
index f9c9cd76be97..367b2aafa5e8 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_mipi.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_mipi.h
@@ -55,7 +55,7 @@ ia_css_mipi_frame_specify(const unsigned int size_mem_words,
*
*/
enum ia_css_err
-ia_css_mipi_frame_enable_check_on_size(const enum ia_css_csi2_port port,
+ia_css_mipi_frame_enable_check_on_size(const enum mipi_port_id port,
const unsigned int size_mem_words);
#endif
@@ -74,7 +74,7 @@ ia_css_mipi_frame_enable_check_on_size(const enum ia_css_csi2_port port,
enum ia_css_err
ia_css_mipi_frame_calculate_size(const unsigned int width,
const unsigned int height,
- const enum ia_css_stream_format format,
+ const enum atomisp_input_format format,
const bool hasSOLandEOL,
const unsigned int embedded_data_size_words,
unsigned int *size_mem_words);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_stream_format.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_stream_format.h
index f7e9020a86e1..f97b9eb2b19c 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_stream_format.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_stream_format.h
@@ -20,75 +20,10 @@
*/
#include <type_support.h> /* bool */
-
-/* The ISP streaming input interface supports the following formats.
- * These match the corresponding MIPI formats.
- */
-enum ia_css_stream_format {
- IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY, /** 8 bits per subpixel */
- IA_CSS_STREAM_FORMAT_YUV420_8, /** 8 bits per subpixel */
- IA_CSS_STREAM_FORMAT_YUV420_10, /** 10 bits per subpixel */
- IA_CSS_STREAM_FORMAT_YUV420_16, /** 16 bits per subpixel */
- IA_CSS_STREAM_FORMAT_YUV422_8, /** UYVY..UYVY, 8 bits per subpixel */
- IA_CSS_STREAM_FORMAT_YUV422_10, /** UYVY..UYVY, 10 bits per subpixel */
- IA_CSS_STREAM_FORMAT_YUV422_16, /** UYVY..UYVY, 16 bits per subpixel */
- IA_CSS_STREAM_FORMAT_RGB_444, /** BGR..BGR, 4 bits per subpixel */
- IA_CSS_STREAM_FORMAT_RGB_555, /** BGR..BGR, 5 bits per subpixel */
- IA_CSS_STREAM_FORMAT_RGB_565, /** BGR..BGR, 5 bits B and R, 6 bits G */
- IA_CSS_STREAM_FORMAT_RGB_666, /** BGR..BGR, 6 bits per subpixel */
- IA_CSS_STREAM_FORMAT_RGB_888, /** BGR..BGR, 8 bits per subpixel */
- IA_CSS_STREAM_FORMAT_RAW_6, /** RAW data, 6 bits per pixel */
- IA_CSS_STREAM_FORMAT_RAW_7, /** RAW data, 7 bits per pixel */
- IA_CSS_STREAM_FORMAT_RAW_8, /** RAW data, 8 bits per pixel */
- IA_CSS_STREAM_FORMAT_RAW_10, /** RAW data, 10 bits per pixel */
- IA_CSS_STREAM_FORMAT_RAW_12, /** RAW data, 12 bits per pixel */
- IA_CSS_STREAM_FORMAT_RAW_14, /** RAW data, 14 bits per pixel */
- IA_CSS_STREAM_FORMAT_RAW_16, /** RAW data, 16 bits per pixel, which is
- not specified in CSI-MIPI standard*/
- IA_CSS_STREAM_FORMAT_BINARY_8, /** Binary byte stream, which is target at
- JPEG. */
-
- /* CSI2-MIPI specific format: Generic short packet data. It is used to
- * keep the timing information for the opening/closing of shutters,
- * triggering of flashes and etc.
- */
- IA_CSS_STREAM_FORMAT_GENERIC_SHORT1, /** Generic Short Packet Code 1 */
- IA_CSS_STREAM_FORMAT_GENERIC_SHORT2, /** Generic Short Packet Code 2 */
- IA_CSS_STREAM_FORMAT_GENERIC_SHORT3, /** Generic Short Packet Code 3 */
- IA_CSS_STREAM_FORMAT_GENERIC_SHORT4, /** Generic Short Packet Code 4 */
- IA_CSS_STREAM_FORMAT_GENERIC_SHORT5, /** Generic Short Packet Code 5 */
- IA_CSS_STREAM_FORMAT_GENERIC_SHORT6, /** Generic Short Packet Code 6 */
- IA_CSS_STREAM_FORMAT_GENERIC_SHORT7, /** Generic Short Packet Code 7 */
- IA_CSS_STREAM_FORMAT_GENERIC_SHORT8, /** Generic Short Packet Code 8 */
-
- /* CSI2-MIPI specific format: YUV data.
- */
- IA_CSS_STREAM_FORMAT_YUV420_8_SHIFT, /** YUV420 8-bit (Chroma Shifted Pixel Sampling) */
- IA_CSS_STREAM_FORMAT_YUV420_10_SHIFT, /** YUV420 8-bit (Chroma Shifted Pixel Sampling) */
-
- /* CSI2-MIPI specific format: Generic long packet data
- */
- IA_CSS_STREAM_FORMAT_EMBEDDED, /** Embedded 8-bit non Image Data */
-
- /* CSI2-MIPI specific format: User defined byte-based data. For example,
- * the data transmitter (e.g. the SoC sensor) can keep the JPEG data as
- * the User Defined Data Type 4 and the MPEG data as the
- * User Defined Data Type 7.
- */
- IA_CSS_STREAM_FORMAT_USER_DEF1, /** User defined 8-bit data type 1 */
- IA_CSS_STREAM_FORMAT_USER_DEF2, /** User defined 8-bit data type 2 */
- IA_CSS_STREAM_FORMAT_USER_DEF3, /** User defined 8-bit data type 3 */
- IA_CSS_STREAM_FORMAT_USER_DEF4, /** User defined 8-bit data type 4 */
- IA_CSS_STREAM_FORMAT_USER_DEF5, /** User defined 8-bit data type 5 */
- IA_CSS_STREAM_FORMAT_USER_DEF6, /** User defined 8-bit data type 6 */
- IA_CSS_STREAM_FORMAT_USER_DEF7, /** User defined 8-bit data type 7 */
- IA_CSS_STREAM_FORMAT_USER_DEF8, /** User defined 8-bit data type 8 */
-};
-
-#define IA_CSS_STREAM_FORMAT_NUM IA_CSS_STREAM_FORMAT_USER_DEF8
+#include "../../../include/linux/atomisp_platform.h"
unsigned int ia_css_util_input_format_bpp(
- enum ia_css_stream_format format,
+ enum atomisp_input_format format,
bool two_ppc);
-#endif /* __IA_CSS_STREAM_FORMAT_H */
+#endif /* __ATOMISP_INPUT_FORMAT_H */
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_stream_public.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_stream_public.h
index ca3203357ff5..ddefad330db7 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_stream_public.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/ia_css_stream_public.h
@@ -62,7 +62,7 @@ enum {
*/
struct ia_css_stream_isys_stream_config {
struct ia_css_resolution input_res; /** Resolution of input data */
- enum ia_css_stream_format format; /** Format of input stream. This data
+ enum atomisp_input_format format; /** Format of input stream. This data
format will be mapped to MIPI data
type internally. */
int linked_isys_stream_id; /** default value is -1, other value means
@@ -77,7 +77,7 @@ struct ia_css_stream_input_config {
Used for CSS 2400/1 System and deprecated for other
systems (replaced by input_effective_res in
ia_css_pipe_config) */
- enum ia_css_stream_format format; /** Format of input stream. This data
+ enum atomisp_input_format format; /** Format of input stream. This data
format will be mapped to MIPI data
type internally. */
enum ia_css_bayer_order bayer_order; /** Bayer order for RAW streams */
@@ -257,7 +257,7 @@ ia_css_stream_unload(struct ia_css_stream *stream);
*
* This function will return the stream format.
*/
-enum ia_css_stream_format
+enum atomisp_input_format
ia_css_stream_get_format(const struct ia_css_stream *stream);
/* @brief Check if the stream is configured for 2 pixels per clock
@@ -453,7 +453,7 @@ ia_css_stream_send_input_line(const struct ia_css_stream *stream,
*/
void
ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
- enum ia_css_stream_format format,
+ enum atomisp_input_format format,
const unsigned short *data,
unsigned int width);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm.host.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm.host.h
index b99c0644ab38..675f6e539b3f 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm.host.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm.host.h
@@ -17,7 +17,6 @@
#include "ia_css_bnlm_types.h"
#include "ia_css_bnlm_param.h"
-#include "ia_css_bnlm_default.host.h"
void
ia_css_bnlm_vmem_encode(
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm_default.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm_default.host.c
deleted file mode 100644
index e2eb88c0f123..000000000000
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm_default.host.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Support for Intel Camera Imaging ISP subsystem.
- * Copyright (c) 2015, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- */
-
-#include "ia_css_bnlm_types.h"
-
-const struct ia_css_bnlm_config default_bnlm_config = {
-
- .rad_enable = true,
- .rad_x_origin = 0,
- .rad_y_origin = 0,
- .avg_min_th = 127,
- .max_min_th = 2047,
-
- .exp_coeff_a = 6048,
- .exp_coeff_b = 7828,
- .exp_coeff_c = 0,
- .exp_exponent = 3,
-
- .nl_th = {2252, 2251, 2250},
- .match_quality_max_idx = {2, 3, 3, 1},
-
- .mu_root_lut_thr = {
- 26, 56, 128, 216, 462, 626, 932, 1108, 1480, 1564, 1824, 1896, 2368, 3428, 4560},
- .mu_root_lut_val = {
- 384, 320, 320, 264, 248, 240, 224, 192, 192, 160, 160, 160, 136, 130, 96, 80},
- .sad_norm_lut_thr = {
- 236, 328, 470, 774, 964, 1486, 2294, 3244, 4844, 6524, 6524, 6524, 6524, 6524, 6524},
- .sad_norm_lut_val = {
- 8064, 7680, 7168, 6144, 5120, 3840, 2560, 2304, 1984, 1792, 1792, 1792, 1792, 1792, 1792, 1792},
- .sig_detail_lut_thr = {
- 2936, 3354, 3943, 4896, 5230, 5682, 5996, 7299, 7299, 7299, 7299, 7299, 7299, 7299, 7299},
- .sig_detail_lut_val = {
- 8191, 7680, 7168, 6144, 5120, 4608, 4224, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032, 4032},
- .sig_rad_lut_thr = {
- 18, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20},
- .sig_rad_lut_val = {
- 2560, 7168, 8188, 8188, 8188, 8188, 8188, 8188, 8188, 8188, 8188, 8188, 8188, 8188, 8188, 8188},
- .rad_pow_lut_thr = {
- 0, 7013, 7013, 7013, 7013, 7013, 7013, 7013, 7013, 7013, 7013, 7013, 7013, 7013, 7013},
- .rad_pow_lut_val = {
- 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191},
- .nl_0_lut_thr = {
- 1072, 7000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000, 8000},
- .nl_0_lut_val = {
- 2560, 3072, 5120, 5120, 5120, 5120, 5120, 5120, 5120, 5120, 5120, 5120, 5120, 5120, 5120, 5120},
- .nl_1_lut_thr = {
- 624, 3224, 3392, 7424, 7424, 7424, 7424, 7424, 7424, 7424, 7424, 7424, 7424, 7424, 7424},
- .nl_1_lut_val = {
- 3584, 4608, 5120, 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144},
- .nl_2_lut_thr = {
- 745, 2896, 3720, 6535, 7696, 8040, 8040, 8040, 8040, 8040, 8040, 8040, 8040, 8040, 8040},
- .nl_2_lut_val = {
- 3584, 4608, 6144, 7168, 7936, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191},
- .nl_3_lut_thr = {
- 4848, 4984, 5872, 6000, 6517, 6960, 7944, 8088, 8161, 8161, 8161, 8161, 8161, 8161, 8161},
- .nl_3_lut_val = {
- 3072, 4104, 4608, 5120, 6144, 7168, 7680, 8128, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191},
-
-};
-
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm_default.host.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm_default.host.h
deleted file mode 100644
index f18c8070abba..000000000000
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/bnlm/ia_css_bnlm_default.host.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Support for Intel Camera Imaging ISP subsystem.
- * Copyright (c) 2015, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- */
-
-#ifndef __IA_CSS_BNLM_DEFAULT_HOST_H
-#define __IA_CSS_BNLM_DEFAULT_HOST_H
-
-#include "ia_css_bnlm_types.h"
-extern const struct ia_css_bnlm_config default_bnlm_config;
-
-#endif /* __IA_CSS_BNLM_DEFAULT_HOST_H */
-
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2.host.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2.host.h
index 641564b4af8e..38d10a5237c6 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2.host.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2.host.h
@@ -17,7 +17,6 @@
#include "ia_css_dpc2_types.h"
#include "ia_css_dpc2_param.h"
-#include "ia_css_dpc2_default.host.h"
void
ia_css_dpc2_encode(
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2_default.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2_default.host.c
deleted file mode 100644
index c102601cc635..000000000000
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2_default.host.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Support for Intel Camera Imaging ISP subsystem.
- * Copyright (c) 2015, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- */
-
-#include "ia_css_dpc2_types.h"
-
-const struct ia_css_dpc2_config default_dpc2_config = {
- .metric1 = 1638,
- .metric2 = 128,
- .metric3 = 1638,
- .wb_gain_gr = 512,
- .wb_gain_r = 512,
- .wb_gain_b = 512,
- .wb_gain_gb = 512
-};
-
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2_default.host.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2_default.host.h
deleted file mode 100644
index a1527ce3eddc..000000000000
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/dpc2/ia_css_dpc2_default.host.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Support for Intel Camera Imaging ISP subsystem.
- * Copyright (c) 2015, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- */
-
-#ifndef __IA_CSS_DPC2_DEFAULT_HOST_H
-#define __IA_CSS_DPC2_DEFAULT_HOST_H
-
-#include "ia_css_dpc2_types.h"
-
-extern const struct ia_css_dpc2_config default_dpc2_config;
-
-#endif /* __IA_CSS_DPC2_DEFAULT_HOST_H */
-
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8.host.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8.host.h
index 355ff13273b0..fff932c1364e 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8.host.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8.host.h
@@ -17,7 +17,6 @@
#include "ia_css_eed1_8_types.h"
#include "ia_css_eed1_8_param.h"
-#include "ia_css_eed1_8_default.host.h"
void
ia_css_eed1_8_vmem_encode(
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8_default.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8_default.host.c
deleted file mode 100644
index 3622719dafa5..000000000000
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8_default.host.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Support for Intel Camera Imaging ISP subsystem.
- * Copyright (c) 2015, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- */
-
-#include "ia_css_eed1_8_types.h"
-
-/* The default values for the kernel parameters are based on
- * ISP261 CSS API public parameter list_all.xlsx from 12-09-2014
- * The parameter list is available on the ISP261 sharepoint
- */
-
-/* Default kernel parameters. */
-const struct ia_css_eed1_8_config default_eed1_8_config = {
- .rbzp_strength = 5489,
- .fcstrength = 6554,
- .fcthres_0 = 0,
- .fcthres_1 = 0,
- .fc_sat_coef = 8191,
- .fc_coring_prm = 128,
- .aerel_thres0 = 0,
- .aerel_gain0 = 8191,
- .aerel_thres1 = 16,
- .aerel_gain1 = 20,
- .derel_thres0 = 1229,
- .derel_gain0 = 1,
- .derel_thres1 = 819,
- .derel_gain1 = 1,
- .coring_pos0 = 0,
- .coring_pos1 = 0,
- .coring_neg0 = 0,
- .coring_neg1 = 0,
- .gain_exp = 2,
- .gain_pos0 = 6144,
- .gain_pos1 = 2048,
- .gain_neg0 = 2048,
- .gain_neg1 = 6144,
- .pos_margin0 = 1475,
- .pos_margin1 = 1475,
- .neg_margin0 = 1475,
- .neg_margin1 = 1475,
- .dew_enhance_seg_x = {
- 0,
- 64,
- 272,
- 688,
- 1376,
- 2400,
- 3840,
- 5744,
- 8191
- },
- .dew_enhance_seg_y = {
- 0,
- 144,
- 480,
- 1040,
- 1852,
- 2945,
- 4357,
- 6094,
- 8191
- },
- .dew_enhance_seg_slope = {
- 4608,
- 3308,
- 2757,
- 2417,
- 2186,
- 8033,
- 7473,
- 7020
- },
- .dew_enhance_seg_exp = {
- 2,
- 2,
- 2,
- 2,
- 2,
- 0,
- 0,
- 0
- },
- .dedgew_max = 6144
-};
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8_default.host.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8_default.host.h
deleted file mode 100644
index 782f739ca8b5..000000000000
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/eed1_8/ia_css_eed1_8_default.host.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Support for Intel Camera Imaging ISP subsystem.
- * Copyright (c) 2015, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- */
-
-#ifndef __IA_CSS_EED1_8_DEFAULT_HOST_H
-#define __IA_CSS_EED1_8_DEFAULT_HOST_H
-
-#include "ia_css_eed1_8_types.h"
-
-extern const struct ia_css_eed1_8_config default_eed1_8_config;
-
-#endif /* __IA_CSS_EED1_8_DEFAULT_HOST_H */
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/output/output_1.0/ia_css_output.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/output/output_1.0/ia_css_output.host.c
index 8fdf47c9310c..9efe5e5e4e06 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/output/output_1.0/ia_css_output.host.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/output/output_1.0/ia_css_output.host.c
@@ -60,7 +60,7 @@ ia_css_output_config(
(void)size;
ia_css_dma_configure_from_info(&to->port_b, from->info);
to->width_a_over_b = elems_a / to->port_b.elems;
- to->height = from->info->res.height;
+ to->height = from->info ? from->info->res.height : 0;
to->enable = from->info != NULL;
ia_css_frame_info_to_frame_sp_info(&to->info, from->info);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/raw/raw_1.0/ia_css_raw.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/raw/raw_1.0/ia_css_raw.host.c
index 68a27f0cfba0..fa9ce0fedf23 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/raw/raw_1.0/ia_css_raw.host.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/raw/raw_1.0/ia_css_raw.host.c
@@ -37,34 +37,34 @@ sh_css_elems_bytes_from_info (unsigned raw_bit_depth)
/* MW: These areMIPI / ISYS properties, not camera function properties */
static enum sh_stream_format
-css2isp_stream_format(enum ia_css_stream_format from)
+css2isp_stream_format(enum atomisp_input_format from)
{
switch (from) {
- case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
+ case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
return sh_stream_format_yuv420_legacy;
- case IA_CSS_STREAM_FORMAT_YUV420_8:
- case IA_CSS_STREAM_FORMAT_YUV420_10:
- case IA_CSS_STREAM_FORMAT_YUV420_16:
+ case ATOMISP_INPUT_FORMAT_YUV420_8:
+ case ATOMISP_INPUT_FORMAT_YUV420_10:
+ case ATOMISP_INPUT_FORMAT_YUV420_16:
return sh_stream_format_yuv420;
- case IA_CSS_STREAM_FORMAT_YUV422_8:
- case IA_CSS_STREAM_FORMAT_YUV422_10:
- case IA_CSS_STREAM_FORMAT_YUV422_16:
+ case ATOMISP_INPUT_FORMAT_YUV422_8:
+ case ATOMISP_INPUT_FORMAT_YUV422_10:
+ case ATOMISP_INPUT_FORMAT_YUV422_16:
return sh_stream_format_yuv422;
- case IA_CSS_STREAM_FORMAT_RGB_444:
- case IA_CSS_STREAM_FORMAT_RGB_555:
- case IA_CSS_STREAM_FORMAT_RGB_565:
- case IA_CSS_STREAM_FORMAT_RGB_666:
- case IA_CSS_STREAM_FORMAT_RGB_888:
+ case ATOMISP_INPUT_FORMAT_RGB_444:
+ case ATOMISP_INPUT_FORMAT_RGB_555:
+ case ATOMISP_INPUT_FORMAT_RGB_565:
+ case ATOMISP_INPUT_FORMAT_RGB_666:
+ case ATOMISP_INPUT_FORMAT_RGB_888:
return sh_stream_format_rgb;
- case IA_CSS_STREAM_FORMAT_RAW_6:
- case IA_CSS_STREAM_FORMAT_RAW_7:
- case IA_CSS_STREAM_FORMAT_RAW_8:
- case IA_CSS_STREAM_FORMAT_RAW_10:
- case IA_CSS_STREAM_FORMAT_RAW_12:
- case IA_CSS_STREAM_FORMAT_RAW_14:
- case IA_CSS_STREAM_FORMAT_RAW_16:
+ case ATOMISP_INPUT_FORMAT_RAW_6:
+ case ATOMISP_INPUT_FORMAT_RAW_7:
+ case ATOMISP_INPUT_FORMAT_RAW_8:
+ case ATOMISP_INPUT_FORMAT_RAW_10:
+ case ATOMISP_INPUT_FORMAT_RAW_12:
+ case ATOMISP_INPUT_FORMAT_RAW_14:
+ case ATOMISP_INPUT_FORMAT_RAW_16:
return sh_stream_format_raw;
- case IA_CSS_STREAM_FORMAT_BINARY_8:
+ case ATOMISP_INPUT_FORMAT_BINARY_8:
default:
return sh_stream_format_raw;
}
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/raw/raw_1.0/ia_css_raw_types.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/raw/raw_1.0/ia_css_raw_types.h
index 5c0b8febd79a..ae868eb5e10f 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/raw/raw_1.0/ia_css_raw_types.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/raw/raw_1.0/ia_css_raw_types.h
@@ -28,7 +28,7 @@ struct ia_css_raw_configuration {
const struct ia_css_frame_info *in_info;
const struct ia_css_frame_info *internal_info;
bool two_ppc;
- enum ia_css_stream_format stream_format;
+ enum atomisp_input_format stream_format;
bool deinterleaved;
uint8_t enable_left_padding;
};
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.c
index e775af51c0c0..78a113bfe8f1 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.c
@@ -15,7 +15,7 @@
#include "ia_css_debug.h"
#include "ia_css_tdf.host.h"
-const int16_t g_pyramid[8][8] = {
+static const int16_t g_pyramid[8][8] = {
{128, 384, 640, 896, 896, 640, 384, 128},
{384, 1152, 1920, 2688, 2688, 1920, 1152, 384},
{640, 1920, 3200, 4480, 4480, 3200, 1920, 640},
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.h
index 1b3e759e41a3..bd628a18e839 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf.host.h
@@ -17,7 +17,6 @@
#include "ia_css_tdf_types.h"
#include "ia_css_tdf_param.h"
-#include "ia_css_tdf_default.host.h"
void
ia_css_tdf_vmem_encode(
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf_default.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf_default.host.c
deleted file mode 100644
index 9bb42daf070d..000000000000
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf_default.host.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Support for Intel Camera Imaging ISP subsystem.
- * Copyright (c) 2015, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- */
-
-#include "ia_css_tdf_types.h"
-
-const struct ia_css_tdf_config default_tdf_config = {
- .thres_flat_table = {0},
- .thres_detail_table = {0},
- .epsilon_0 = 4095,
- .epsilon_1 = 5733,
- .eps_scale_text = 409,
- .eps_scale_edge = 3686,
- .sepa_flat = 1294,
- .sepa_edge = 4095,
- .blend_flat = 819,
- .blend_text = 819,
- .blend_edge = 8191,
- .shading_gain = 1024,
- .shading_base_gain = 8191,
- .local_y_gain = 0,
- .local_y_base_gain = 2047,
- .rad_x_origin = 0,
- .rad_y_origin = 0
-};
-
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf_default.host.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf_default.host.h
deleted file mode 100644
index cd8fb70e5a87..000000000000
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/tdf/tdf_1.0/ia_css_tdf_default.host.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Support for Intel Camera Imaging ISP subsystem.
- * Copyright (c) 2015, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- */
-
-#ifndef __IA_CSS_TDF_DEFAULT_HOST_H
-#define __IA_CSS_TDF_DEFAULT_HOST_H
-
-#include "ia_css_tdf_types.h"
-
-extern const struct ia_css_tdf_config default_tdf_config;
-
-#endif /* __IA_CSS_TDF_DEFAULT_HOST_H */
-
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/vf/vf_1.0/ia_css_vf.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/vf/vf_1.0/ia_css_vf.host.c
index 5610833ed595..c2076e412410 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/vf/vf_1.0/ia_css_vf.host.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/vf/vf_1.0/ia_css_vf.host.c
@@ -130,11 +130,11 @@ ia_css_vf_configure(
err = configure_kernel(info, out_info, vf_info, downscale_log2, &config);
configure_dma(&config, vf_info);
- if (binary) {
- if (vf_info)
- vf_info->raw_bit_depth = info->dma.vfdec_bits_per_pixel;
- ia_css_configure_vf (binary, &config);
- }
+
+ if (vf_info)
+ vf_info->raw_bit_depth = info->dma.vfdec_bits_per_pixel;
+ ia_css_configure_vf (binary, &config);
+
return IA_CSS_SUCCESS;
}
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/interface/ia_css_binary.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/interface/ia_css_binary.h
index 732e49a241eb..b62c4d321a4e 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/interface/ia_css_binary.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/interface/ia_css_binary.h
@@ -113,7 +113,7 @@ struct ia_css_binary_descr {
#endif
bool enable_capture_pp_bli;
struct ia_css_resolution dvs_env;
- enum ia_css_stream_format stream_format;
+ enum atomisp_input_format stream_format;
struct ia_css_frame_info *in_info; /* the info of the input-frame with the
ISP required resolution. */
struct ia_css_frame_info *bds_out_info;
@@ -126,7 +126,7 @@ struct ia_css_binary_descr {
struct ia_css_binary {
const struct ia_css_binary_xinfo *info;
- enum ia_css_stream_format input_format;
+ enum atomisp_input_format input_format;
struct ia_css_frame_info in_frame_info;
struct ia_css_frame_info internal_frame_info;
struct ia_css_frame_info out_frame_info[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
@@ -162,7 +162,7 @@ struct ia_css_binary {
#define IA_CSS_BINARY_DEFAULT_SETTINGS \
(struct ia_css_binary) { \
- .input_format = IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY, \
+ .input_format = ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY, \
.in_frame_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO, \
.internal_frame_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO, \
.out_frame_info = {IA_CSS_BINARY_DEFAULT_FRAME_INFO}, \
@@ -179,7 +179,7 @@ enum ia_css_err
ia_css_binary_fill_info(const struct ia_css_binary_xinfo *xinfo,
bool online,
bool two_ppc,
- enum ia_css_stream_format stream_format,
+ enum atomisp_input_format stream_format,
const struct ia_css_frame_info *in_info,
const struct ia_css_frame_info *bds_out_info,
const struct ia_css_frame_info *out_info[],
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/src/binary.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/src/binary.c
index a0f0e9062c4c..0cd6e1da43cf 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/src/binary.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/binary/src/binary.c
@@ -861,7 +861,7 @@ binary_supports_output_format(const struct ia_css_binary_xinfo *info,
#ifdef ISP2401
static bool
binary_supports_input_format(const struct ia_css_binary_xinfo *info,
- enum ia_css_stream_format format)
+ enum atomisp_input_format format)
{
assert(info != NULL);
@@ -1088,7 +1088,7 @@ enum ia_css_err
ia_css_binary_fill_info(const struct ia_css_binary_xinfo *xinfo,
bool online,
bool two_ppc,
- enum ia_css_stream_format stream_format,
+ enum atomisp_input_format stream_format,
const struct ia_css_frame_info *in_info, /* can be NULL */
const struct ia_css_frame_info *bds_out_info, /* can be NULL */
const struct ia_css_frame_info *out_info[], /* can be NULL */
@@ -1382,7 +1382,7 @@ ia_css_binary_find(struct ia_css_binary_descr *descr,
int mode;
bool online;
bool two_ppc;
- enum ia_css_stream_format stream_format;
+ enum atomisp_input_format stream_format;
const struct ia_css_frame_info *req_in_info,
*req_bds_out_info,
*req_out_info[IA_CSS_BINARY_MAX_OUTPUT_PORTS],
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/bufq/src/bufq.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/bufq/src/bufq.c
index e50d9f2e2609..ffbcdd80d934 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/bufq/src/bufq.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/bufq/src/bufq.c
@@ -90,12 +90,11 @@ struct sh_css_queues {
#endif
-struct sh_css_queues css_queues;
-
-
/*******************************************************
*** Static variables
********************************************************/
+static struct sh_css_queues css_queues;
+
static int buffer_type_to_queue_id_map[SH_CSS_MAX_SP_THREADS][IA_CSS_NUM_DYNAMIC_BUFFER_TYPE];
static bool queue_availability[SH_CSS_MAX_SP_THREADS][SH_CSS_MAX_NUM_QUEUES];
@@ -207,7 +206,7 @@ static void map_buffer_type_to_queue_id(
}
for (i = SH_CSS_QUEUE_C_ID; i < SH_CSS_MAX_NUM_QUEUES; i++) {
- if (queue_availability[thread_id][i] == true) {
+ if (queue_availability[thread_id][i]) {
queue_availability[thread_id][i] = false;
buffer_type_to_queue_id_map[thread_id][buf_type] = i;
break;
@@ -266,7 +265,7 @@ static ia_css_queue_t *bufq_get_qhandle(
case sh_css_sp2host_isys_event_queue:
q = &css_queues.sp2host_isys_event_queue_handle;
break;
-#endif
+#endif
case sh_css_host2sp_tag_cmd_queue:
q = &css_queues.host2sp_tag_cmd_queue_handle;
break;
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/src/ia_css_debug.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/src/ia_css_debug.c
index 60395904f89a..4607a76dc78a 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/src/ia_css_debug.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/debug/src/ia_css_debug.c
@@ -110,9 +110,6 @@
/* Global variable to store the dtrace verbosity level */
unsigned int ia_css_debug_trace_level = IA_CSS_DEBUG_WARNING;
-/* Assumes that IA_CSS_STREAM_FORMAT_BINARY_8 is last */
-#define N_IA_CSS_STREAM_FORMAT (IA_CSS_STREAM_FORMAT_BINARY_8+1)
-
#define DPG_START "ia_css_debug_pipe_graph_dump_start "
#define DPG_END " ia_css_debug_pipe_graph_dump_end\n"
@@ -141,8 +138,8 @@ static struct pipe_graph_class {
int width;
int eff_height;
int eff_width;
- enum ia_css_stream_format stream_format;
-} pg_inst = {true, 0, 0, 0, 0, N_IA_CSS_STREAM_FORMAT};
+ enum atomisp_input_format stream_format;
+} pg_inst = {true, 0, 0, 0, 0, N_ATOMISP_INPUT_FORMAT};
static const char * const queue_id_to_str[] = {
/* [SH_CSS_QUEUE_A_ID] =*/ "queue_A",
@@ -261,86 +258,86 @@ unsigned int ia_css_debug_get_dtrace_level(void)
return ia_css_debug_trace_level;
}
-static const char *debug_stream_format2str(const enum ia_css_stream_format stream_format)
+static const char *debug_stream_format2str(const enum atomisp_input_format stream_format)
{
switch (stream_format) {
- case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
+ case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
return "yuv420-8-legacy";
- case IA_CSS_STREAM_FORMAT_YUV420_8:
+ case ATOMISP_INPUT_FORMAT_YUV420_8:
return "yuv420-8";
- case IA_CSS_STREAM_FORMAT_YUV420_10:
+ case ATOMISP_INPUT_FORMAT_YUV420_10:
return "yuv420-10";
- case IA_CSS_STREAM_FORMAT_YUV420_16:
+ case ATOMISP_INPUT_FORMAT_YUV420_16:
return "yuv420-16";
- case IA_CSS_STREAM_FORMAT_YUV422_8:
+ case ATOMISP_INPUT_FORMAT_YUV422_8:
return "yuv422-8";
- case IA_CSS_STREAM_FORMAT_YUV422_10:
+ case ATOMISP_INPUT_FORMAT_YUV422_10:
return "yuv422-10";
- case IA_CSS_STREAM_FORMAT_YUV422_16:
+ case ATOMISP_INPUT_FORMAT_YUV422_16:
return "yuv422-16";
- case IA_CSS_STREAM_FORMAT_RGB_444:
+ case ATOMISP_INPUT_FORMAT_RGB_444:
return "rgb444";
- case IA_CSS_STREAM_FORMAT_RGB_555:
+ case ATOMISP_INPUT_FORMAT_RGB_555:
return "rgb555";
- case IA_CSS_STREAM_FORMAT_RGB_565:
+ case ATOMISP_INPUT_FORMAT_RGB_565:
return "rgb565";
- case IA_CSS_STREAM_FORMAT_RGB_666:
+ case ATOMISP_INPUT_FORMAT_RGB_666:
return "rgb666";
- case IA_CSS_STREAM_FORMAT_RGB_888:
+ case ATOMISP_INPUT_FORMAT_RGB_888:
return "rgb888";
- case IA_CSS_STREAM_FORMAT_RAW_6:
+ case ATOMISP_INPUT_FORMAT_RAW_6:
return "raw6";
- case IA_CSS_STREAM_FORMAT_RAW_7:
+ case ATOMISP_INPUT_FORMAT_RAW_7:
return "raw7";
- case IA_CSS_STREAM_FORMAT_RAW_8:
+ case ATOMISP_INPUT_FORMAT_RAW_8:
return "raw8";
- case IA_CSS_STREAM_FORMAT_RAW_10:
+ case ATOMISP_INPUT_FORMAT_RAW_10:
return "raw10";
- case IA_CSS_STREAM_FORMAT_RAW_12:
+ case ATOMISP_INPUT_FORMAT_RAW_12:
return "raw12";
- case IA_CSS_STREAM_FORMAT_RAW_14:
+ case ATOMISP_INPUT_FORMAT_RAW_14:
return "raw14";
- case IA_CSS_STREAM_FORMAT_RAW_16:
+ case ATOMISP_INPUT_FORMAT_RAW_16:
return "raw16";
- case IA_CSS_STREAM_FORMAT_BINARY_8:
+ case ATOMISP_INPUT_FORMAT_BINARY_8:
return "binary8";
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT1:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT1:
return "generic-short1";
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT2:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT2:
return "generic-short2";
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT3:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT3:
return "generic-short3";
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT4:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT4:
return "generic-short4";
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT5:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT5:
return "generic-short5";
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT6:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT6:
return "generic-short6";
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT7:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT7:
return "generic-short7";
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT8:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT8:
return "generic-short8";
- case IA_CSS_STREAM_FORMAT_YUV420_8_SHIFT:
+ case ATOMISP_INPUT_FORMAT_YUV420_8_SHIFT:
return "yuv420-8-shift";
- case IA_CSS_STREAM_FORMAT_YUV420_10_SHIFT:
+ case ATOMISP_INPUT_FORMAT_YUV420_10_SHIFT:
return "yuv420-10-shift";
- case IA_CSS_STREAM_FORMAT_EMBEDDED:
+ case ATOMISP_INPUT_FORMAT_EMBEDDED:
return "embedded-8";
- case IA_CSS_STREAM_FORMAT_USER_DEF1:
+ case ATOMISP_INPUT_FORMAT_USER_DEF1:
return "user-def-8-type-1";
- case IA_CSS_STREAM_FORMAT_USER_DEF2:
+ case ATOMISP_INPUT_FORMAT_USER_DEF2:
return "user-def-8-type-2";
- case IA_CSS_STREAM_FORMAT_USER_DEF3:
+ case ATOMISP_INPUT_FORMAT_USER_DEF3:
return "user-def-8-type-3";
- case IA_CSS_STREAM_FORMAT_USER_DEF4:
+ case ATOMISP_INPUT_FORMAT_USER_DEF4:
return "user-def-8-type-4";
- case IA_CSS_STREAM_FORMAT_USER_DEF5:
+ case ATOMISP_INPUT_FORMAT_USER_DEF5:
return "user-def-8-type-5";
- case IA_CSS_STREAM_FORMAT_USER_DEF6:
+ case ATOMISP_INPUT_FORMAT_USER_DEF6:
return "user-def-8-type-6";
- case IA_CSS_STREAM_FORMAT_USER_DEF7:
+ case ATOMISP_INPUT_FORMAT_USER_DEF7:
return "user-def-8-type-7";
- case IA_CSS_STREAM_FORMAT_USER_DEF8:
+ case ATOMISP_INPUT_FORMAT_USER_DEF8:
return "user-def-8-type-8";
default:
@@ -2679,9 +2676,9 @@ ia_css_debug_pipe_graph_dump_frame(
}
dtrace_dot(
"node [shape = box, "
- "fixedsize=true, width=2, height=0.7]; \"0x%08lx\" "
+ "fixedsize=true, width=2, height=0.7]; \"%p\" "
"[label = \"%s\\n%d(%d) x %d, %dbpp\\n%s\"];",
- HOST_ADDRESS(frame),
+ frame,
debug_frame_format2str(frame->info.format),
frame->info.res.width,
frame->info.padded_width,
@@ -2691,16 +2688,16 @@ ia_css_debug_pipe_graph_dump_frame(
if (in_frame) {
dtrace_dot(
- "\"0x%08lx\"->\"%s(pipe%d)\" "
+ "\"%p\"->\"%s(pipe%d)\" "
"[label = %s_frame];",
- HOST_ADDRESS(frame),
+ frame,
blob_name, id, frame_name);
} else {
dtrace_dot(
- "\"%s(pipe%d)\"->\"0x%08lx\" "
+ "\"%s(pipe%d)\"->\"%p\" "
"[label = %s_frame];",
blob_name, id,
- HOST_ADDRESS(frame),
+ frame,
frame_name);
}
}
@@ -2730,7 +2727,7 @@ void ia_css_debug_pipe_graph_dump_epilogue(void)
}
- if (pg_inst.stream_format != N_IA_CSS_STREAM_FORMAT) {
+ if (pg_inst.stream_format != N_ATOMISP_INPUT_FORMAT) {
/* An input stream format has been set so assume we have
* an input system and sensor
*/
@@ -2770,7 +2767,7 @@ void ia_css_debug_pipe_graph_dump_epilogue(void)
pg_inst.height = 0;
pg_inst.eff_width = 0;
pg_inst.eff_height = 0;
- pg_inst.stream_format = N_IA_CSS_STREAM_FORMAT;
+ pg_inst.stream_format = N_ATOMISP_INPUT_FORMAT;
}
void
@@ -3011,9 +3008,9 @@ ia_css_debug_pipe_graph_dump_sp_raw_copy(
snprintf(ring_buffer, sizeof(ring_buffer),
"node [shape = box, "
- "fixedsize=true, width=2, height=0.7]; \"0x%08lx\" "
+ "fixedsize=true, width=2, height=0.7]; \"%p\" "
"[label = \"%s\\n%d(%d) x %d\\nRingbuffer\"];",
- HOST_ADDRESS(out_frame),
+ out_frame,
debug_frame_format2str(out_frame->info.format),
out_frame->info.res.width,
out_frame->info.padded_width,
@@ -3022,9 +3019,9 @@ ia_css_debug_pipe_graph_dump_sp_raw_copy(
dtrace_dot(ring_buffer);
dtrace_dot(
- "\"%s(pipe%d)\"->\"0x%08lx\" "
+ "\"%s(pipe%d)\"->\"%p\" "
"[label = out_frame];",
- "sp_raw_copy", 1, HOST_ADDRESS(out_frame));
+ "sp_raw_copy", 1, out_frame);
snprintf(dot_id_input_bin, sizeof(dot_id_input_bin), "%s(pipe%d)", "sp_raw_copy", 1);
}
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/ifmtr/src/ifmtr.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/ifmtr/src/ifmtr.c
index adefa57820a4..1bed027435fd 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/ifmtr/src/ifmtr.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/ifmtr/src/ifmtr.c
@@ -112,13 +112,13 @@ enum ia_css_err ia_css_ifmtr_configure(struct ia_css_stream_config *config,
width_b_factor = 1, start_column_b,
left_padding = 0;
input_formatter_cfg_t if_a_config, if_b_config;
- enum ia_css_stream_format input_format;
+ enum atomisp_input_format input_format;
enum ia_css_err err = IA_CSS_SUCCESS;
uint8_t if_config_index;
/* Determine which input formatter config set is targeted. */
/* Index is equal to the CSI-2 port used. */
- enum ia_css_csi2_port port;
+ enum mipi_port_id port;
if (binary) {
cropped_height = binary->in_frame_info.res.height;
@@ -141,7 +141,7 @@ enum ia_css_err ia_css_ifmtr_configure(struct ia_css_stream_config *config,
if (config->mode == IA_CSS_INPUT_MODE_SENSOR
|| config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
port = config->source.port.port;
- if_config_index = (uint8_t) (port - IA_CSS_CSI2_PORT0);
+ if_config_index = (uint8_t) (port - MIPI_PORT0_ID);
} else if (config->mode == IA_CSS_INPUT_MODE_MEMORY) {
if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
} else {
@@ -189,7 +189,7 @@ enum ia_css_err ia_css_ifmtr_configure(struct ia_css_stream_config *config,
bits_per_pixel = input_formatter_get_alignment(INPUT_FORMATTER0_ID)
* 8 / ISP_VEC_NELEMS;
switch (input_format) {
- case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
+ case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
if (two_ppc) {
vmem_increment = 1;
deinterleaving = 1;
@@ -219,9 +219,9 @@ enum ia_css_err ia_css_ifmtr_configure(struct ia_css_stream_config *config,
start_column = start_column * deinterleaving / 2;
}
break;
- case IA_CSS_STREAM_FORMAT_YUV420_8:
- case IA_CSS_STREAM_FORMAT_YUV420_10:
- case IA_CSS_STREAM_FORMAT_YUV420_16:
+ case ATOMISP_INPUT_FORMAT_YUV420_8:
+ case ATOMISP_INPUT_FORMAT_YUV420_10:
+ case ATOMISP_INPUT_FORMAT_YUV420_16:
if (two_ppc) {
vmem_increment = 1;
deinterleaving = 1;
@@ -246,9 +246,9 @@ enum ia_css_err ia_css_ifmtr_configure(struct ia_css_stream_config *config,
start_column *= deinterleaving;
}
break;
- case IA_CSS_STREAM_FORMAT_YUV422_8:
- case IA_CSS_STREAM_FORMAT_YUV422_10:
- case IA_CSS_STREAM_FORMAT_YUV422_16:
+ case ATOMISP_INPUT_FORMAT_YUV422_8:
+ case ATOMISP_INPUT_FORMAT_YUV422_10:
+ case ATOMISP_INPUT_FORMAT_YUV422_16:
if (two_ppc) {
vmem_increment = 1;
deinterleaving = 1;
@@ -267,11 +267,11 @@ enum ia_css_err ia_css_ifmtr_configure(struct ia_css_stream_config *config,
start_column *= deinterleaving;
}
break;
- case IA_CSS_STREAM_FORMAT_RGB_444:
- case IA_CSS_STREAM_FORMAT_RGB_555:
- case IA_CSS_STREAM_FORMAT_RGB_565:
- case IA_CSS_STREAM_FORMAT_RGB_666:
- case IA_CSS_STREAM_FORMAT_RGB_888:
+ case ATOMISP_INPUT_FORMAT_RGB_444:
+ case ATOMISP_INPUT_FORMAT_RGB_555:
+ case ATOMISP_INPUT_FORMAT_RGB_565:
+ case ATOMISP_INPUT_FORMAT_RGB_666:
+ case ATOMISP_INPUT_FORMAT_RGB_888:
num_vectors *= 2;
if (two_ppc) {
deinterleaving = 2; /* BR in if_a, G in if_b */
@@ -293,11 +293,11 @@ enum ia_css_err ia_css_ifmtr_configure(struct ia_css_stream_config *config,
num_vectors = num_vectors / 2 * deinterleaving;
buf_offset_b = buffer_width / 2 / ISP_VEC_NELEMS;
break;
- case IA_CSS_STREAM_FORMAT_RAW_6:
- case IA_CSS_STREAM_FORMAT_RAW_7:
- case IA_CSS_STREAM_FORMAT_RAW_8:
- case IA_CSS_STREAM_FORMAT_RAW_10:
- case IA_CSS_STREAM_FORMAT_RAW_12:
+ case ATOMISP_INPUT_FORMAT_RAW_6:
+ case ATOMISP_INPUT_FORMAT_RAW_7:
+ case ATOMISP_INPUT_FORMAT_RAW_8:
+ case ATOMISP_INPUT_FORMAT_RAW_10:
+ case ATOMISP_INPUT_FORMAT_RAW_12:
if (two_ppc) {
int crop_col = (start_column % 2) == 1;
vmem_increment = 2;
@@ -332,8 +332,8 @@ enum ia_css_err ia_css_ifmtr_configure(struct ia_css_stream_config *config,
vectors_per_line = CEIL_DIV(cropped_width, ISP_VEC_NELEMS);
vectors_per_line = CEIL_MUL(vectors_per_line, deinterleaving);
break;
- case IA_CSS_STREAM_FORMAT_RAW_14:
- case IA_CSS_STREAM_FORMAT_RAW_16:
+ case ATOMISP_INPUT_FORMAT_RAW_14:
+ case ATOMISP_INPUT_FORMAT_RAW_16:
if (two_ppc) {
num_vectors *= 2;
vmem_increment = 1;
@@ -350,26 +350,26 @@ enum ia_css_err ia_css_ifmtr_configure(struct ia_css_stream_config *config,
}
buffer_height *= 2;
break;
- case IA_CSS_STREAM_FORMAT_BINARY_8:
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT1:
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT2:
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT3:
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT4:
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT5:
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT6:
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT7:
- case IA_CSS_STREAM_FORMAT_GENERIC_SHORT8:
- case IA_CSS_STREAM_FORMAT_YUV420_8_SHIFT:
- case IA_CSS_STREAM_FORMAT_YUV420_10_SHIFT:
- case IA_CSS_STREAM_FORMAT_EMBEDDED:
- case IA_CSS_STREAM_FORMAT_USER_DEF1:
- case IA_CSS_STREAM_FORMAT_USER_DEF2:
- case IA_CSS_STREAM_FORMAT_USER_DEF3:
- case IA_CSS_STREAM_FORMAT_USER_DEF4:
- case IA_CSS_STREAM_FORMAT_USER_DEF5:
- case IA_CSS_STREAM_FORMAT_USER_DEF6:
- case IA_CSS_STREAM_FORMAT_USER_DEF7:
- case IA_CSS_STREAM_FORMAT_USER_DEF8:
+ case ATOMISP_INPUT_FORMAT_BINARY_8:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT1:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT2:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT3:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT4:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT5:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT6:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT7:
+ case ATOMISP_INPUT_FORMAT_GENERIC_SHORT8:
+ case ATOMISP_INPUT_FORMAT_YUV420_8_SHIFT:
+ case ATOMISP_INPUT_FORMAT_YUV420_10_SHIFT:
+ case ATOMISP_INPUT_FORMAT_EMBEDDED:
+ case ATOMISP_INPUT_FORMAT_USER_DEF1:
+ case ATOMISP_INPUT_FORMAT_USER_DEF2:
+ case ATOMISP_INPUT_FORMAT_USER_DEF3:
+ case ATOMISP_INPUT_FORMAT_USER_DEF4:
+ case ATOMISP_INPUT_FORMAT_USER_DEF5:
+ case ATOMISP_INPUT_FORMAT_USER_DEF6:
+ case ATOMISP_INPUT_FORMAT_USER_DEF7:
+ case ATOMISP_INPUT_FORMAT_USER_DEF8:
break;
}
if (width_a == 0)
@@ -420,9 +420,9 @@ enum ia_css_err ia_css_ifmtr_configure(struct ia_css_stream_config *config,
if_a_config.buf_eol_offset =
buffer_width * bits_per_pixel / 8 - line_width;
if_a_config.is_yuv420_format =
- (input_format == IA_CSS_STREAM_FORMAT_YUV420_8)
- || (input_format == IA_CSS_STREAM_FORMAT_YUV420_10)
- || (input_format == IA_CSS_STREAM_FORMAT_YUV420_16);
+ (input_format == ATOMISP_INPUT_FORMAT_YUV420_8)
+ || (input_format == ATOMISP_INPUT_FORMAT_YUV420_10)
+ || (input_format == ATOMISP_INPUT_FORMAT_YUV420_16);
if_a_config.block_no_reqs = (config->mode != IA_CSS_INPUT_MODE_SENSOR);
if (two_ppc) {
@@ -449,9 +449,9 @@ enum ia_css_err ia_css_ifmtr_configure(struct ia_css_stream_config *config,
if_b_config.buf_eol_offset =
buffer_width * bits_per_pixel / 8 - line_width;
if_b_config.is_yuv420_format =
- input_format == IA_CSS_STREAM_FORMAT_YUV420_8
- || input_format == IA_CSS_STREAM_FORMAT_YUV420_10
- || input_format == IA_CSS_STREAM_FORMAT_YUV420_16;
+ input_format == ATOMISP_INPUT_FORMAT_YUV420_8
+ || input_format == ATOMISP_INPUT_FORMAT_YUV420_10
+ || input_format == ATOMISP_INPUT_FORMAT_YUV420_16;
if_b_config.block_no_reqs =
(config->mode != IA_CSS_INPUT_MODE_SENSOR);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/inputfifo/interface/ia_css_inputfifo.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/inputfifo/interface/ia_css_inputfifo.h
index 47d0f7e53f47..545f9e2da59e 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/inputfifo/interface/ia_css_inputfifo.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/inputfifo/interface/ia_css_inputfifo.h
@@ -42,12 +42,12 @@ void ia_css_inputfifo_send_input_frame(
unsigned int width,
unsigned int height,
unsigned int ch_id,
- enum ia_css_stream_format input_format,
+ enum atomisp_input_format input_format,
bool two_ppc);
void ia_css_inputfifo_start_frame(
unsigned int ch_id,
- enum ia_css_stream_format input_format,
+ enum atomisp_input_format input_format,
bool two_ppc);
void ia_css_inputfifo_send_line(
@@ -59,7 +59,7 @@ void ia_css_inputfifo_send_line(
void ia_css_inputfifo_send_embedded_line(
unsigned int ch_id,
- enum ia_css_stream_format data_type,
+ enum atomisp_input_format data_type,
const unsigned short *data,
unsigned int width);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/inputfifo/src/inputfifo.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/inputfifo/src/inputfifo.c
index 8dc74927e9a2..24ca4aaf8df1 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/inputfifo/src/inputfifo.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/inputfifo/src/inputfifo.c
@@ -86,7 +86,7 @@ static unsigned int inputfifo_curr_ch_id, inputfifo_curr_fmt_type;
#endif
struct inputfifo_instance {
unsigned int ch_id;
- enum ia_css_stream_format input_format;
+ enum atomisp_input_format input_format;
bool two_ppc;
bool streaming;
unsigned int hblank_cycles;
@@ -466,21 +466,21 @@ static void inputfifo_send_frame(
static enum inputfifo_mipi_data_type inputfifo_determine_type(
- enum ia_css_stream_format input_format)
+ enum atomisp_input_format input_format)
{
enum inputfifo_mipi_data_type type;
type = inputfifo_mipi_data_type_regular;
- if (input_format == IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY) {
+ if (input_format == ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) {
type =
inputfifo_mipi_data_type_yuv420_legacy;
- } else if (input_format == IA_CSS_STREAM_FORMAT_YUV420_8 ||
- input_format == IA_CSS_STREAM_FORMAT_YUV420_10 ||
- input_format == IA_CSS_STREAM_FORMAT_YUV420_16) {
+ } else if (input_format == ATOMISP_INPUT_FORMAT_YUV420_8 ||
+ input_format == ATOMISP_INPUT_FORMAT_YUV420_10 ||
+ input_format == ATOMISP_INPUT_FORMAT_YUV420_16) {
type =
inputfifo_mipi_data_type_yuv420;
- } else if (input_format >= IA_CSS_STREAM_FORMAT_RGB_444 &&
- input_format <= IA_CSS_STREAM_FORMAT_RGB_888) {
+ } else if (input_format >= ATOMISP_INPUT_FORMAT_RGB_444 &&
+ input_format <= ATOMISP_INPUT_FORMAT_RGB_888) {
type =
inputfifo_mipi_data_type_rgb;
}
@@ -500,7 +500,7 @@ void ia_css_inputfifo_send_input_frame(
unsigned int width,
unsigned int height,
unsigned int ch_id,
- enum ia_css_stream_format input_format,
+ enum atomisp_input_format input_format,
bool two_ppc)
{
unsigned int fmt_type, hblank_cycles, marker_cycles;
@@ -524,7 +524,7 @@ void ia_css_inputfifo_send_input_frame(
void ia_css_inputfifo_start_frame(
unsigned int ch_id,
- enum ia_css_stream_format input_format,
+ enum atomisp_input_format input_format,
bool two_ppc)
{
struct inputfifo_instance *s2mi;
@@ -574,7 +574,7 @@ void ia_css_inputfifo_send_line(
void ia_css_inputfifo_send_embedded_line(
unsigned int ch_id,
- enum ia_css_stream_format data_type,
+ enum atomisp_input_format data_type,
const unsigned short *data,
unsigned int width)
{
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/interface/ia_css_isys.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/interface/ia_css_isys.h
index 4cf2defe9ef0..8c005db9766e 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/interface/ia_css_isys.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/interface/ia_css_isys.h
@@ -50,8 +50,8 @@ typedef input_system_cfg_t ia_css_isys_descr_t;
#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
input_system_error_t ia_css_isys_init(void);
void ia_css_isys_uninit(void);
-mipi_port_ID_t ia_css_isys_port_to_mipi_port(
- enum ia_css_csi2_port api_port);
+enum mipi_port_id ia_css_isys_port_to_mipi_port(
+ enum mipi_port_id api_port);
#endif
#if defined(USE_INPUT_SYSTEM_VERSION_2401)
@@ -68,7 +68,7 @@ mipi_port_ID_t ia_css_isys_port_to_mipi_port(
* there is already a stream registered with the same handle
*/
enum ia_css_err ia_css_isys_csi_rx_register_stream(
- enum ia_css_csi2_port port,
+ enum mipi_port_id port,
uint32_t isys_stream_id);
/**
@@ -83,14 +83,14 @@ enum ia_css_err ia_css_isys_csi_rx_register_stream(
* there is no stream registered with that handle
*/
enum ia_css_err ia_css_isys_csi_rx_unregister_stream(
- enum ia_css_csi2_port port,
+ enum mipi_port_id port,
uint32_t isys_stream_id);
enum ia_css_err ia_css_isys_convert_compressed_format(
struct ia_css_csi2_compression *comp,
struct input_system_cfg_s *cfg);
unsigned int ia_css_csi2_calculate_input_system_alignment(
- enum ia_css_stream_format fmt_type);
+ enum atomisp_input_format fmt_type);
#endif
#if !defined(USE_INPUT_SYSTEM_VERSION_2401)
@@ -101,12 +101,12 @@ void ia_css_isys_rx_configure(
void ia_css_isys_rx_disable(void);
-void ia_css_isys_rx_enable_all_interrupts(mipi_port_ID_t port);
+void ia_css_isys_rx_enable_all_interrupts(enum mipi_port_id port);
-unsigned int ia_css_isys_rx_get_interrupt_reg(mipi_port_ID_t port);
-void ia_css_isys_rx_get_irq_info(mipi_port_ID_t port,
+unsigned int ia_css_isys_rx_get_interrupt_reg(enum mipi_port_id port);
+void ia_css_isys_rx_get_irq_info(enum mipi_port_id port,
unsigned int *irq_infos);
-void ia_css_isys_rx_clear_irq_info(mipi_port_ID_t port,
+void ia_css_isys_rx_clear_irq_info(enum mipi_port_id port,
unsigned int irq_infos);
unsigned int ia_css_isys_rx_translate_irq_infos(unsigned int bits);
@@ -124,7 +124,7 @@ unsigned int ia_css_isys_rx_translate_irq_infos(unsigned int bits);
* format type must be sumitted correctly by the application.
*/
enum ia_css_err ia_css_isys_convert_stream_format_to_mipi_format(
- enum ia_css_stream_format input_format,
+ enum atomisp_input_format input_format,
mipi_predictor_t compression,
unsigned int *fmt_type);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/csi_rx_rmgr.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/csi_rx_rmgr.c
index 3b04dc51335a..a914ce5532ec 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/csi_rx_rmgr.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/csi_rx_rmgr.c
@@ -141,7 +141,7 @@ void ia_css_isys_csi_rx_lut_rmgr_release(
}
enum ia_css_err ia_css_isys_csi_rx_register_stream(
- enum ia_css_csi2_port port,
+ enum mipi_port_id port,
uint32_t isys_stream_id)
{
enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR;
@@ -160,7 +160,7 @@ enum ia_css_err ia_css_isys_csi_rx_register_stream(
}
enum ia_css_err ia_css_isys_csi_rx_unregister_stream(
- enum ia_css_csi2_port port,
+ enum mipi_port_id port,
uint32_t isys_stream_id)
{
enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR;
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/isys_init.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/isys_init.c
index 4122084fd237..2ae5e59d5e31 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/isys_init.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/isys_init.c
@@ -105,8 +105,6 @@ input_system_error_t ia_css_isys_init(void)
#elif defined(USE_INPUT_SYSTEM_VERSION_2401)
input_system_error_t ia_css_isys_init(void)
{
- input_system_error_t error = INPUT_SYSTEM_ERR_NO_ERROR;
-
ia_css_isys_csi_rx_lut_rmgr_init();
ia_css_isys_ibuf_rmgr_init();
ia_css_isys_dma_channel_rmgr_init();
@@ -120,7 +118,7 @@ input_system_error_t ia_css_isys_init(void)
isys_irqc_status_enable(ISYS_IRQ1_ID);
isys_irqc_status_enable(ISYS_IRQ2_ID);
- return error;
+ return INPUT_SYSTEM_ERR_NO_ERROR;
}
#endif
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/rx.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/rx.c
index 70f6cb5e5918..425bd3cc3f34 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/rx.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/rx.c
@@ -36,7 +36,7 @@ more details.
#include "sh_css_internal.h"
#if !defined(USE_INPUT_SYSTEM_VERSION_2401)
-void ia_css_isys_rx_enable_all_interrupts(mipi_port_ID_t port)
+void ia_css_isys_rx_enable_all_interrupts(enum mipi_port_id port)
{
hrt_data bits = receiver_port_reg_load(RX0_ID,
port,
@@ -80,22 +80,22 @@ void ia_css_isys_rx_enable_all_interrupts(mipi_port_ID_t port)
* initializers in Windows. Without that there is no easy way to guarantee
* that the array values would be in the correct order.
* */
-mipi_port_ID_t ia_css_isys_port_to_mipi_port(enum ia_css_csi2_port api_port)
+enum mipi_port_id ia_css_isys_port_to_mipi_port(enum mipi_port_id api_port)
{
/* In this module the validity of the inptu variable should
* have been checked already, so we do not check for erroneous
* values. */
- mipi_port_ID_t port = MIPI_PORT0_ID;
+ enum mipi_port_id port = MIPI_PORT0_ID;
- if (api_port == IA_CSS_CSI2_PORT1)
+ if (api_port == MIPI_PORT1_ID)
port = MIPI_PORT1_ID;
- else if (api_port == IA_CSS_CSI2_PORT2)
+ else if (api_port == MIPI_PORT2_ID)
port = MIPI_PORT2_ID;
return port;
}
-unsigned int ia_css_isys_rx_get_interrupt_reg(mipi_port_ID_t port)
+unsigned int ia_css_isys_rx_get_interrupt_reg(enum mipi_port_id port)
{
return receiver_port_reg_load(RX0_ID,
port,
@@ -104,17 +104,17 @@ unsigned int ia_css_isys_rx_get_interrupt_reg(mipi_port_ID_t port)
void ia_css_rx_get_irq_info(unsigned int *irq_infos)
{
- ia_css_rx_port_get_irq_info(IA_CSS_CSI2_PORT1, irq_infos);
+ ia_css_rx_port_get_irq_info(MIPI_PORT1_ID, irq_infos);
}
-void ia_css_rx_port_get_irq_info(enum ia_css_csi2_port api_port,
+void ia_css_rx_port_get_irq_info(enum mipi_port_id api_port,
unsigned int *irq_infos)
{
- mipi_port_ID_t port = ia_css_isys_port_to_mipi_port(api_port);
+ enum mipi_port_id port = ia_css_isys_port_to_mipi_port(api_port);
ia_css_isys_rx_get_irq_info(port, irq_infos);
}
-void ia_css_isys_rx_get_irq_info(mipi_port_ID_t port,
+void ia_css_isys_rx_get_irq_info(enum mipi_port_id port,
unsigned int *irq_infos)
{
unsigned int bits;
@@ -169,16 +169,16 @@ unsigned int ia_css_isys_rx_translate_irq_infos(unsigned int bits)
void ia_css_rx_clear_irq_info(unsigned int irq_infos)
{
- ia_css_rx_port_clear_irq_info(IA_CSS_CSI2_PORT1, irq_infos);
+ ia_css_rx_port_clear_irq_info(MIPI_PORT1_ID, irq_infos);
}
-void ia_css_rx_port_clear_irq_info(enum ia_css_csi2_port api_port, unsigned int irq_infos)
+void ia_css_rx_port_clear_irq_info(enum mipi_port_id api_port, unsigned int irq_infos)
{
- mipi_port_ID_t port = ia_css_isys_port_to_mipi_port(api_port);
+ enum mipi_port_id port = ia_css_isys_port_to_mipi_port(api_port);
ia_css_isys_rx_clear_irq_info(port, irq_infos);
}
-void ia_css_isys_rx_clear_irq_info(mipi_port_ID_t port, unsigned int irq_infos)
+void ia_css_isys_rx_clear_irq_info(enum mipi_port_id port, unsigned int irq_infos)
{
hrt_data bits = receiver_port_reg_load(RX0_ID,
port,
@@ -229,7 +229,7 @@ void ia_css_isys_rx_clear_irq_info(mipi_port_ID_t port, unsigned int irq_infos)
#endif /* #if !defined(USE_INPUT_SYSTEM_VERSION_2401) */
enum ia_css_err ia_css_isys_convert_stream_format_to_mipi_format(
- enum ia_css_stream_format input_format,
+ enum atomisp_input_format input_format,
mipi_predictor_t compression,
unsigned int *fmt_type)
{
@@ -244,25 +244,25 @@ enum ia_css_err ia_css_isys_convert_stream_format_to_mipi_format(
*/
if (compression != MIPI_PREDICTOR_NONE) {
switch (input_format) {
- case IA_CSS_STREAM_FORMAT_RAW_6:
+ case ATOMISP_INPUT_FORMAT_RAW_6:
*fmt_type = 6;
break;
- case IA_CSS_STREAM_FORMAT_RAW_7:
+ case ATOMISP_INPUT_FORMAT_RAW_7:
*fmt_type = 7;
break;
- case IA_CSS_STREAM_FORMAT_RAW_8:
+ case ATOMISP_INPUT_FORMAT_RAW_8:
*fmt_type = 8;
break;
- case IA_CSS_STREAM_FORMAT_RAW_10:
+ case ATOMISP_INPUT_FORMAT_RAW_10:
*fmt_type = 10;
break;
- case IA_CSS_STREAM_FORMAT_RAW_12:
+ case ATOMISP_INPUT_FORMAT_RAW_12:
*fmt_type = 12;
break;
- case IA_CSS_STREAM_FORMAT_RAW_14:
+ case ATOMISP_INPUT_FORMAT_RAW_14:
*fmt_type = 14;
break;
- case IA_CSS_STREAM_FORMAT_RAW_16:
+ case ATOMISP_INPUT_FORMAT_RAW_16:
*fmt_type = 16;
break;
default:
@@ -277,96 +277,96 @@ enum ia_css_err ia_css_isys_convert_stream_format_to_mipi_format(
* MW: For some reason the mapping is not 1-to-1
*/
switch (input_format) {
- case IA_CSS_STREAM_FORMAT_RGB_888:
+ case ATOMISP_INPUT_FORMAT_RGB_888:
*fmt_type = MIPI_FORMAT_RGB888;
break;
- case IA_CSS_STREAM_FORMAT_RGB_555:
+ case ATOMISP_INPUT_FORMAT_RGB_555:
*fmt_type = MIPI_FORMAT_RGB555;
break;
- case IA_CSS_STREAM_FORMAT_RGB_444:
+ case ATOMISP_INPUT_FORMAT_RGB_444:
*fmt_type = MIPI_FORMAT_RGB444;
break;
- case IA_CSS_STREAM_FORMAT_RGB_565:
+ case ATOMISP_INPUT_FORMAT_RGB_565:
*fmt_type = MIPI_FORMAT_RGB565;
break;
- case IA_CSS_STREAM_FORMAT_RGB_666:
+ case ATOMISP_INPUT_FORMAT_RGB_666:
*fmt_type = MIPI_FORMAT_RGB666;
break;
- case IA_CSS_STREAM_FORMAT_RAW_8:
+ case ATOMISP_INPUT_FORMAT_RAW_8:
*fmt_type = MIPI_FORMAT_RAW8;
break;
- case IA_CSS_STREAM_FORMAT_RAW_10:
+ case ATOMISP_INPUT_FORMAT_RAW_10:
*fmt_type = MIPI_FORMAT_RAW10;
break;
- case IA_CSS_STREAM_FORMAT_RAW_6:
+ case ATOMISP_INPUT_FORMAT_RAW_6:
*fmt_type = MIPI_FORMAT_RAW6;
break;
- case IA_CSS_STREAM_FORMAT_RAW_7:
+ case ATOMISP_INPUT_FORMAT_RAW_7:
*fmt_type = MIPI_FORMAT_RAW7;
break;
- case IA_CSS_STREAM_FORMAT_RAW_12:
+ case ATOMISP_INPUT_FORMAT_RAW_12:
*fmt_type = MIPI_FORMAT_RAW12;
break;
- case IA_CSS_STREAM_FORMAT_RAW_14:
+ case ATOMISP_INPUT_FORMAT_RAW_14:
*fmt_type = MIPI_FORMAT_RAW14;
break;
- case IA_CSS_STREAM_FORMAT_YUV420_8:
+ case ATOMISP_INPUT_FORMAT_YUV420_8:
*fmt_type = MIPI_FORMAT_YUV420_8;
break;
- case IA_CSS_STREAM_FORMAT_YUV420_10:
+ case ATOMISP_INPUT_FORMAT_YUV420_10:
*fmt_type = MIPI_FORMAT_YUV420_10;
break;
- case IA_CSS_STREAM_FORMAT_YUV422_8:
+ case ATOMISP_INPUT_FORMAT_YUV422_8:
*fmt_type = MIPI_FORMAT_YUV422_8;
break;
- case IA_CSS_STREAM_FORMAT_YUV422_10:
+ case ATOMISP_INPUT_FORMAT_YUV422_10:
*fmt_type = MIPI_FORMAT_YUV422_10;
break;
- case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
+ case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
*fmt_type = MIPI_FORMAT_YUV420_8_LEGACY;
break;
- case IA_CSS_STREAM_FORMAT_EMBEDDED:
+ case ATOMISP_INPUT_FORMAT_EMBEDDED:
*fmt_type = MIPI_FORMAT_EMBEDDED;
break;
#ifndef USE_INPUT_SYSTEM_VERSION_2401
- case IA_CSS_STREAM_FORMAT_RAW_16:
+ case ATOMISP_INPUT_FORMAT_RAW_16:
/* This is not specified by Arasan, so we use
* 17 for now.
*/
*fmt_type = MIPI_FORMAT_RAW16;
break;
- case IA_CSS_STREAM_FORMAT_BINARY_8:
+ case ATOMISP_INPUT_FORMAT_BINARY_8:
*fmt_type = MIPI_FORMAT_BINARY_8;
break;
#else
- case IA_CSS_STREAM_FORMAT_USER_DEF1:
+ case ATOMISP_INPUT_FORMAT_USER_DEF1:
*fmt_type = MIPI_FORMAT_CUSTOM0;
break;
- case IA_CSS_STREAM_FORMAT_USER_DEF2:
+ case ATOMISP_INPUT_FORMAT_USER_DEF2:
*fmt_type = MIPI_FORMAT_CUSTOM1;
break;
- case IA_CSS_STREAM_FORMAT_USER_DEF3:
+ case ATOMISP_INPUT_FORMAT_USER_DEF3:
*fmt_type = MIPI_FORMAT_CUSTOM2;
break;
- case IA_CSS_STREAM_FORMAT_USER_DEF4:
+ case ATOMISP_INPUT_FORMAT_USER_DEF4:
*fmt_type = MIPI_FORMAT_CUSTOM3;
break;
- case IA_CSS_STREAM_FORMAT_USER_DEF5:
+ case ATOMISP_INPUT_FORMAT_USER_DEF5:
*fmt_type = MIPI_FORMAT_CUSTOM4;
break;
- case IA_CSS_STREAM_FORMAT_USER_DEF6:
+ case ATOMISP_INPUT_FORMAT_USER_DEF6:
*fmt_type = MIPI_FORMAT_CUSTOM5;
break;
- case IA_CSS_STREAM_FORMAT_USER_DEF7:
+ case ATOMISP_INPUT_FORMAT_USER_DEF7:
*fmt_type = MIPI_FORMAT_CUSTOM6;
break;
- case IA_CSS_STREAM_FORMAT_USER_DEF8:
+ case ATOMISP_INPUT_FORMAT_USER_DEF8:
*fmt_type = MIPI_FORMAT_CUSTOM7;
break;
#endif
- case IA_CSS_STREAM_FORMAT_YUV420_16:
- case IA_CSS_STREAM_FORMAT_YUV422_16:
+ case ATOMISP_INPUT_FORMAT_YUV420_16:
+ case ATOMISP_INPUT_FORMAT_YUV422_16:
default:
return IA_CSS_ERR_INTERNAL_ERROR;
}
@@ -448,34 +448,34 @@ enum ia_css_err ia_css_isys_convert_compressed_format(
}
unsigned int ia_css_csi2_calculate_input_system_alignment(
- enum ia_css_stream_format fmt_type)
+ enum atomisp_input_format fmt_type)
{
unsigned int memory_alignment_in_bytes = HIVE_ISP_DDR_WORD_BYTES;
switch (fmt_type) {
- case IA_CSS_STREAM_FORMAT_RAW_6:
- case IA_CSS_STREAM_FORMAT_RAW_7:
- case IA_CSS_STREAM_FORMAT_RAW_8:
- case IA_CSS_STREAM_FORMAT_RAW_10:
- case IA_CSS_STREAM_FORMAT_RAW_12:
- case IA_CSS_STREAM_FORMAT_RAW_14:
+ case ATOMISP_INPUT_FORMAT_RAW_6:
+ case ATOMISP_INPUT_FORMAT_RAW_7:
+ case ATOMISP_INPUT_FORMAT_RAW_8:
+ case ATOMISP_INPUT_FORMAT_RAW_10:
+ case ATOMISP_INPUT_FORMAT_RAW_12:
+ case ATOMISP_INPUT_FORMAT_RAW_14:
memory_alignment_in_bytes = 2 * ISP_VEC_NELEMS;
break;
- case IA_CSS_STREAM_FORMAT_YUV420_8:
- case IA_CSS_STREAM_FORMAT_YUV422_8:
- case IA_CSS_STREAM_FORMAT_USER_DEF1:
- case IA_CSS_STREAM_FORMAT_USER_DEF2:
- case IA_CSS_STREAM_FORMAT_USER_DEF3:
- case IA_CSS_STREAM_FORMAT_USER_DEF4:
- case IA_CSS_STREAM_FORMAT_USER_DEF5:
- case IA_CSS_STREAM_FORMAT_USER_DEF6:
- case IA_CSS_STREAM_FORMAT_USER_DEF7:
- case IA_CSS_STREAM_FORMAT_USER_DEF8:
+ case ATOMISP_INPUT_FORMAT_YUV420_8:
+ case ATOMISP_INPUT_FORMAT_YUV422_8:
+ case ATOMISP_INPUT_FORMAT_USER_DEF1:
+ case ATOMISP_INPUT_FORMAT_USER_DEF2:
+ case ATOMISP_INPUT_FORMAT_USER_DEF3:
+ case ATOMISP_INPUT_FORMAT_USER_DEF4:
+ case ATOMISP_INPUT_FORMAT_USER_DEF5:
+ case ATOMISP_INPUT_FORMAT_USER_DEF6:
+ case ATOMISP_INPUT_FORMAT_USER_DEF7:
+ case ATOMISP_INPUT_FORMAT_USER_DEF8:
/* Planar YUV formats need to have all planes aligned, this means
* double the alignment for the Y plane if the horizontal decimation is 2. */
memory_alignment_in_bytes = 2 * HIVE_ISP_DDR_WORD_BYTES;
break;
- case IA_CSS_STREAM_FORMAT_EMBEDDED:
+ case ATOMISP_INPUT_FORMAT_EMBEDDED:
default:
memory_alignment_in_bytes = HIVE_ISP_DDR_WORD_BYTES;
break;
@@ -492,7 +492,7 @@ void ia_css_isys_rx_configure(const rx_cfg_t *config,
#if defined(HAS_RX_VERSION_2)
bool port_enabled[N_MIPI_PORT_ID];
bool any_port_enabled = false;
- mipi_port_ID_t port;
+ enum mipi_port_id port;
if ((config == NULL)
|| (config->mode >= N_RX_MODE)
@@ -500,7 +500,7 @@ void ia_css_isys_rx_configure(const rx_cfg_t *config,
assert(0);
return;
}
- for (port = (mipi_port_ID_t) 0; port < N_MIPI_PORT_ID; port++) {
+ for (port = (enum mipi_port_id) 0; port < N_MIPI_PORT_ID; port++) {
if (is_receiver_port_enabled(RX0_ID, port))
any_port_enabled = true;
}
@@ -595,8 +595,8 @@ void ia_css_isys_rx_configure(const rx_cfg_t *config,
void ia_css_isys_rx_disable(void)
{
- mipi_port_ID_t port;
- for (port = (mipi_port_ID_t) 0; port < N_MIPI_PORT_ID; port++) {
+ enum mipi_port_id port;
+ for (port = (enum mipi_port_id) 0; port < N_MIPI_PORT_ID; port++) {
receiver_port_reg_store(RX0_ID, port,
_HRT_CSS_RECEIVER_DEVICE_READY_REG_IDX,
false);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/virtual_isys.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/virtual_isys.c
index 90922a7acefd..2484949453b7 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/virtual_isys.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/isys/src/virtual_isys.c
@@ -331,7 +331,7 @@ static bool create_input_system_channel(
break;
}
- if (rc == false)
+ if (!rc)
return false;
if (!acquire_sid(me->stream2mmio_id, &(me->stream2mmio_sid_id))) {
@@ -474,7 +474,7 @@ static bool calculate_input_system_channel_cfg(
rc = calculate_stream2mmio_cfg(isys_cfg, metadata,
&(channel_cfg->stream2mmio_cfg));
- if (rc == false)
+ if (!rc)
return false;
rc = calculate_ibuf_ctrl_cfg(
@@ -482,7 +482,7 @@ static bool calculate_input_system_channel_cfg(
input_port,
isys_cfg,
&(channel_cfg->ibuf_ctrl_cfg));
- if (rc == false)
+ if (!rc)
return false;
if (metadata)
channel_cfg->ibuf_ctrl_cfg.stores_per_frame = isys_cfg->metadata.lines_per_frame;
@@ -491,7 +491,7 @@ static bool calculate_input_system_channel_cfg(
channel,
isys_cfg,
&(channel_cfg->dma_cfg));
- if (rc == false)
+ if (!rc)
return false;
rc = calculate_isys2401_dma_port_cfg(
@@ -499,7 +499,7 @@ static bool calculate_input_system_channel_cfg(
false,
metadata,
&(channel_cfg->dma_src_port_cfg));
- if (rc == false)
+ if (!rc)
return false;
rc = calculate_isys2401_dma_port_cfg(
@@ -507,7 +507,7 @@ static bool calculate_input_system_channel_cfg(
isys_cfg->raw_packed,
metadata,
&(channel_cfg->dma_dest_port_cfg));
- if (rc == false)
+ if (!rc)
return false;
return true;
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/pipeline/src/pipeline.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/pipeline/src/pipeline.c
index 81a50c73ad0b..4746620ca212 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/pipeline/src/pipeline.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/pipeline/src/pipeline.c
@@ -161,9 +161,9 @@ void ia_css_pipeline_start(enum ia_css_pipe_id pipe_id,
#endif
#if !defined(HAS_NO_INPUT_SYSTEM)
#ifndef ISP2401
- , (mipi_port_ID_t) 0
+ , (enum mipi_port_id) 0
#else
- (mipi_port_ID_t) 0,
+ (enum mipi_port_id) 0,
#endif
#endif
#ifndef ISP2401
@@ -574,7 +574,7 @@ static void pipeline_map_num_to_sp_thread(unsigned int pipe_num)
But the below is more descriptive.
*/
- assert(found_sp_thread != false);
+ assert(found_sp_thread);
}
static void pipeline_unmap_num_to_sp_thread(unsigned int pipe_num)
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/rmgr/src/rmgr_vbuf.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/rmgr/src/rmgr_vbuf.c
index 54239ac9d7c9..a4d8a48f95ba 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/rmgr/src/rmgr_vbuf.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/rmgr/src/rmgr_vbuf.c
@@ -24,12 +24,12 @@
* @brief VBUF resource handles
*/
#define NUM_HANDLES 1000
-struct ia_css_rmgr_vbuf_handle handle_table[NUM_HANDLES];
+static struct ia_css_rmgr_vbuf_handle handle_table[NUM_HANDLES];
/*
* @brief VBUF resource pool - refpool
*/
-struct ia_css_rmgr_vbuf_pool refpool = {
+static struct ia_css_rmgr_vbuf_pool refpool = {
false, /* copy_on_write */
false, /* recycle */
0, /* size */
@@ -40,7 +40,7 @@ struct ia_css_rmgr_vbuf_pool refpool = {
/*
* @brief VBUF resource pool - writepool
*/
-struct ia_css_rmgr_vbuf_pool writepool = {
+static struct ia_css_rmgr_vbuf_pool writepool = {
true, /* copy_on_write */
false, /* recycle */
0, /* size */
@@ -51,7 +51,7 @@ struct ia_css_rmgr_vbuf_pool writepool = {
/*
* @brief VBUF resource pool - hmmbufferpool
*/
-struct ia_css_rmgr_vbuf_pool hmmbufferpool = {
+static struct ia_css_rmgr_vbuf_pool hmmbufferpool = {
true, /* copy_on_write */
true, /* recycle */
32, /* size */
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c
index 37116faab631..c771e4b910f3 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c
@@ -462,46 +462,46 @@ verify_copy_out_frame_format(struct ia_css_pipe *pipe)
assert(pipe->stream != NULL);
switch (pipe->stream->config.input_config.format) {
- case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
- case IA_CSS_STREAM_FORMAT_YUV420_8:
+ case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
+ case ATOMISP_INPUT_FORMAT_YUV420_8:
for (i=0; i<ARRAY_SIZE(yuv420_copy_formats) && !found; i++)
found = (out_fmt == yuv420_copy_formats[i]);
break;
- case IA_CSS_STREAM_FORMAT_YUV420_10:
- case IA_CSS_STREAM_FORMAT_YUV420_16:
+ case ATOMISP_INPUT_FORMAT_YUV420_10:
+ case ATOMISP_INPUT_FORMAT_YUV420_16:
found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
break;
- case IA_CSS_STREAM_FORMAT_YUV422_8:
+ case ATOMISP_INPUT_FORMAT_YUV422_8:
for (i=0; i<ARRAY_SIZE(yuv422_copy_formats) && !found; i++)
found = (out_fmt == yuv422_copy_formats[i]);
break;
- case IA_CSS_STREAM_FORMAT_YUV422_10:
- case IA_CSS_STREAM_FORMAT_YUV422_16:
+ case ATOMISP_INPUT_FORMAT_YUV422_10:
+ case ATOMISP_INPUT_FORMAT_YUV422_16:
found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 ||
out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
break;
- case IA_CSS_STREAM_FORMAT_RGB_444:
- case IA_CSS_STREAM_FORMAT_RGB_555:
- case IA_CSS_STREAM_FORMAT_RGB_565:
+ case ATOMISP_INPUT_FORMAT_RGB_444:
+ case ATOMISP_INPUT_FORMAT_RGB_555:
+ case ATOMISP_INPUT_FORMAT_RGB_565:
found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
out_fmt == IA_CSS_FRAME_FORMAT_RGB565);
break;
- case IA_CSS_STREAM_FORMAT_RGB_666:
- case IA_CSS_STREAM_FORMAT_RGB_888:
+ case ATOMISP_INPUT_FORMAT_RGB_666:
+ case ATOMISP_INPUT_FORMAT_RGB_888:
found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
out_fmt == IA_CSS_FRAME_FORMAT_YUV420);
break;
- case IA_CSS_STREAM_FORMAT_RAW_6:
- case IA_CSS_STREAM_FORMAT_RAW_7:
- case IA_CSS_STREAM_FORMAT_RAW_8:
- case IA_CSS_STREAM_FORMAT_RAW_10:
- case IA_CSS_STREAM_FORMAT_RAW_12:
- case IA_CSS_STREAM_FORMAT_RAW_14:
- case IA_CSS_STREAM_FORMAT_RAW_16:
+ case ATOMISP_INPUT_FORMAT_RAW_6:
+ case ATOMISP_INPUT_FORMAT_RAW_7:
+ case ATOMISP_INPUT_FORMAT_RAW_8:
+ case ATOMISP_INPUT_FORMAT_RAW_10:
+ case ATOMISP_INPUT_FORMAT_RAW_12:
+ case ATOMISP_INPUT_FORMAT_RAW_14:
+ case ATOMISP_INPUT_FORMAT_RAW_16:
found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) ||
(out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED);
break;
- case IA_CSS_STREAM_FORMAT_BINARY_8:
+ case ATOMISP_INPUT_FORMAT_BINARY_8:
found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8);
break;
default:
@@ -586,13 +586,13 @@ sh_css_config_input_network(struct ia_css_stream *stream)
}
#elif !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
- enum ia_css_stream_format format,
+ enum atomisp_input_format format,
unsigned int pixels_per_line)
{
unsigned int rval;
switch (format) {
- case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
+ case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
/*
* The frame format layout is shown below.
*
@@ -611,9 +611,9 @@ static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
*/
rval = pixels_per_line * 2;
break;
- case IA_CSS_STREAM_FORMAT_YUV420_8:
- case IA_CSS_STREAM_FORMAT_YUV420_10:
- case IA_CSS_STREAM_FORMAT_YUV420_16:
+ case ATOMISP_INPUT_FORMAT_YUV420_8:
+ case ATOMISP_INPUT_FORMAT_YUV420_10:
+ case ATOMISP_INPUT_FORMAT_YUV420_16:
/*
* The frame format layout is shown below.
*
@@ -630,9 +630,9 @@ static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
*/
rval = pixels_per_line * 2;
break;
- case IA_CSS_STREAM_FORMAT_YUV422_8:
- case IA_CSS_STREAM_FORMAT_YUV422_10:
- case IA_CSS_STREAM_FORMAT_YUV422_16:
+ case ATOMISP_INPUT_FORMAT_YUV422_8:
+ case ATOMISP_INPUT_FORMAT_YUV422_10:
+ case ATOMISP_INPUT_FORMAT_YUV422_16:
/*
* The frame format layout is shown below.
*
@@ -649,11 +649,11 @@ static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
*/
rval = pixels_per_line * 2;
break;
- case IA_CSS_STREAM_FORMAT_RGB_444:
- case IA_CSS_STREAM_FORMAT_RGB_555:
- case IA_CSS_STREAM_FORMAT_RGB_565:
- case IA_CSS_STREAM_FORMAT_RGB_666:
- case IA_CSS_STREAM_FORMAT_RGB_888:
+ case ATOMISP_INPUT_FORMAT_RGB_444:
+ case ATOMISP_INPUT_FORMAT_RGB_555:
+ case ATOMISP_INPUT_FORMAT_RGB_565:
+ case ATOMISP_INPUT_FORMAT_RGB_666:
+ case ATOMISP_INPUT_FORMAT_RGB_888:
/*
* The frame format layout is shown below.
*
@@ -670,22 +670,22 @@ static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
*/
rval = pixels_per_line * 4;
break;
- case IA_CSS_STREAM_FORMAT_RAW_6:
- case IA_CSS_STREAM_FORMAT_RAW_7:
- case IA_CSS_STREAM_FORMAT_RAW_8:
- case IA_CSS_STREAM_FORMAT_RAW_10:
- case IA_CSS_STREAM_FORMAT_RAW_12:
- case IA_CSS_STREAM_FORMAT_RAW_14:
- case IA_CSS_STREAM_FORMAT_RAW_16:
- case IA_CSS_STREAM_FORMAT_BINARY_8:
- case IA_CSS_STREAM_FORMAT_USER_DEF1:
- case IA_CSS_STREAM_FORMAT_USER_DEF2:
- case IA_CSS_STREAM_FORMAT_USER_DEF3:
- case IA_CSS_STREAM_FORMAT_USER_DEF4:
- case IA_CSS_STREAM_FORMAT_USER_DEF5:
- case IA_CSS_STREAM_FORMAT_USER_DEF6:
- case IA_CSS_STREAM_FORMAT_USER_DEF7:
- case IA_CSS_STREAM_FORMAT_USER_DEF8:
+ case ATOMISP_INPUT_FORMAT_RAW_6:
+ case ATOMISP_INPUT_FORMAT_RAW_7:
+ case ATOMISP_INPUT_FORMAT_RAW_8:
+ case ATOMISP_INPUT_FORMAT_RAW_10:
+ case ATOMISP_INPUT_FORMAT_RAW_12:
+ case ATOMISP_INPUT_FORMAT_RAW_14:
+ case ATOMISP_INPUT_FORMAT_RAW_16:
+ case ATOMISP_INPUT_FORMAT_BINARY_8:
+ case ATOMISP_INPUT_FORMAT_USER_DEF1:
+ case ATOMISP_INPUT_FORMAT_USER_DEF2:
+ case ATOMISP_INPUT_FORMAT_USER_DEF3:
+ case ATOMISP_INPUT_FORMAT_USER_DEF4:
+ case ATOMISP_INPUT_FORMAT_USER_DEF5:
+ case ATOMISP_INPUT_FORMAT_USER_DEF6:
+ case ATOMISP_INPUT_FORMAT_USER_DEF7:
+ case ATOMISP_INPUT_FORMAT_USER_DEF8:
/*
* The frame format layout is shown below.
*
@@ -742,11 +742,11 @@ static bool sh_css_translate_stream_cfg_to_input_system_input_port_id(
break;
case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
- if (stream_cfg->source.port.port == IA_CSS_CSI2_PORT0) {
+ if (stream_cfg->source.port.port == MIPI_PORT0_ID) {
isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID;
- } else if (stream_cfg->source.port.port == IA_CSS_CSI2_PORT1) {
+ } else if (stream_cfg->source.port.port == MIPI_PORT1_ID) {
isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID;
- } else if (stream_cfg->source.port.port == IA_CSS_CSI2_PORT2) {
+ } else if (stream_cfg->source.port.port == MIPI_PORT2_ID) {
isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID;
}
@@ -927,7 +927,7 @@ static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
unsigned int max_subpixels_per_line;
unsigned int lines_per_frame;
unsigned int align_req_in_bytes;
- enum ia_css_stream_format fmt_type;
+ enum atomisp_input_format fmt_type;
fmt_type = stream_cfg->isys_config[isys_stream_idx].format;
if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR ||
@@ -936,11 +936,11 @@ static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
UNCOMPRESSED_BITS_PER_PIXEL_10) {
- fmt_type = IA_CSS_STREAM_FORMAT_RAW_10;
+ fmt_type = ATOMISP_INPUT_FORMAT_RAW_10;
}
else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
UNCOMPRESSED_BITS_PER_PIXEL_12) {
- fmt_type = IA_CSS_STREAM_FORMAT_RAW_12;
+ fmt_type = ATOMISP_INPUT_FORMAT_RAW_12;
}
else
return false;
@@ -1082,7 +1082,7 @@ sh_css_config_input_network(struct ia_css_stream *stream)
/* get the SP thread id */
rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id);
- if (rc != true)
+ if (!rc)
return IA_CSS_ERR_INTERNAL_ERROR;
/* get the target input terminal */
sp_pipeline_input_terminal = &(sh_css_sp_group.pipe_io[sp_thread_id].input);
@@ -1108,7 +1108,7 @@ sh_css_config_input_network(struct ia_css_stream *stream)
&(isys_stream_descr));
}
- if (rc != true)
+ if (!rc)
return IA_CSS_ERR_INTERNAL_ERROR;
isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i);
@@ -1118,7 +1118,7 @@ sh_css_config_input_network(struct ia_css_stream *stream)
&(isys_stream_descr),
&(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]),
isys_stream_id);
- if (rc != true)
+ if (!rc)
return IA_CSS_ERR_INTERNAL_ERROR;
/* calculate the configuration of the virtual Input System (2401) */
@@ -1126,7 +1126,7 @@ sh_css_config_input_network(struct ia_css_stream *stream)
&(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]),
&(isys_stream_descr),
&(sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i]));
- if (rc != true) {
+ if (!rc) {
ia_css_isys_stream_destroy(&(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]));
return IA_CSS_ERR_INTERNAL_ERROR;
}
@@ -1195,7 +1195,7 @@ static inline struct ia_css_pipe *stream_get_target_pipe(
static enum ia_css_err stream_csi_rx_helper(
struct ia_css_stream *stream,
- enum ia_css_err (*func)(enum ia_css_csi2_port, uint32_t))
+ enum ia_css_err (*func)(enum mipi_port_id, uint32_t))
{
enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR;
uint32_t sp_thread_id, stream_id;
@@ -1391,7 +1391,7 @@ start_copy_on_sp(struct ia_css_pipe *pipe,
ia_css_isys_rx_disable();
#endif
- if (pipe->stream->config.input_config.format != IA_CSS_STREAM_FORMAT_BINARY_8)
+ if (pipe->stream->config.input_config.format != ATOMISP_INPUT_FORMAT_BINARY_8)
return IA_CSS_ERR_INTERNAL_ERROR;
sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2);
@@ -1454,7 +1454,7 @@ static void start_pipe(
&me->stream->info.metadata_info
#if !defined(HAS_NO_INPUT_SYSTEM)
,(input_mode==IA_CSS_INPUT_MODE_MEMORY) ?
- (mipi_port_ID_t)0 :
+ (enum mipi_port_id)0 :
me->stream->config.source.port.port
#endif
#ifdef ISP2401
@@ -1497,7 +1497,7 @@ static void
enable_interrupts(enum ia_css_irq_type irq_type)
{
#ifdef USE_INPUT_SYSTEM_VERSION_2
- mipi_port_ID_t port;
+ enum mipi_port_id port;
#endif
bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE;
IA_CSS_ENTER_PRIVATE("");
@@ -2562,7 +2562,7 @@ ia_css_uninit(void)
ifmtr_set_if_blocking_mode_reset = true;
#endif
- if (fw_explicitly_loaded == false) {
+ if (!fw_explicitly_loaded) {
ia_css_unload_firmware();
}
ia_css_spctrl_unload_fw(SP0_ID);
@@ -4074,9 +4074,9 @@ preview_start(struct ia_css_pipe *pipe)
#endif
#if !defined(HAS_NO_INPUT_SYSTEM)
#ifndef ISP2401
- , (mipi_port_ID_t)0
+ , (enum mipi_port_id)0
#else
- (mipi_port_ID_t)0,
+ (enum mipi_port_id)0,
#endif
#endif
#ifndef ISP2401
@@ -4106,9 +4106,9 @@ preview_start(struct ia_css_pipe *pipe)
#endif
#if !defined(HAS_NO_INPUT_SYSTEM)
#ifndef ISP2401
- , (mipi_port_ID_t) 0
+ , (enum mipi_port_id) 0
#else
- (mipi_port_ID_t) 0,
+ (enum mipi_port_id) 0,
#endif
#endif
#ifndef ISP2401
@@ -4673,7 +4673,7 @@ ia_css_dequeue_psys_event(struct ia_css_event *event)
event->type = convert_event_sp_to_host_domain[payload[0]];
/* Some sane default values since not all events use all fields. */
event->pipe = NULL;
- event->port = IA_CSS_CSI2_PORT0;
+ event->port = MIPI_PORT0_ID;
event->exp_id = 0;
event->fw_warning = IA_CSS_FW_WARNING_NONE;
event->fw_handle = 0;
@@ -4719,7 +4719,7 @@ ia_css_dequeue_psys_event(struct ia_css_event *event)
}
}
if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) {
- event->port = (enum ia_css_csi2_port)payload[1];
+ event->port = (enum mipi_port_id)payload[1];
event->exp_id = payload[3];
} else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) {
event->fw_warning = (enum ia_css_fw_warning)payload[1];
@@ -5949,9 +5949,9 @@ static enum ia_css_err video_start(struct ia_css_pipe *pipe)
#endif
#if !defined(HAS_NO_INPUT_SYSTEM)
#ifndef ISP2401
- , (mipi_port_ID_t)0
+ , (enum mipi_port_id)0
#else
- (mipi_port_ID_t)0,
+ (enum mipi_port_id)0,
#endif
#endif
#ifndef ISP2401
@@ -6784,7 +6784,7 @@ static bool copy_on_sp(struct ia_css_pipe *pipe)
rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW);
- rval &= ((pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_BINARY_8) ||
+ rval &= ((pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) ||
(pipe->config.mode == IA_CSS_PIPE_MODE_COPY));
return rval;
@@ -6817,7 +6817,7 @@ static enum ia_css_err load_capture_binaries(
return err;
}
if (copy_on_sp(pipe) &&
- pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_BINARY_8) {
+ pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
ia_css_frame_info_init(
&pipe->output_info[0],
JPEG_BYTES,
@@ -6915,7 +6915,7 @@ need_yuv_scaler_stage(const struct ia_css_pipe *pipe)
/* TODO: make generic function */
need_format_conversion =
- ((pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY) &&
+ ((pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) &&
(pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8));
in_res = pipe->config.input_effective_res;
@@ -7304,7 +7304,7 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe)
/*
* NOTES
* - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when
- * its input is "IA_CSS_STREAM_FORMAT_YUV422_8"?
+ * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"?
*
* In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_
* binary". However, the "yuv_scale_binary" does NOT support the input-frame
@@ -7319,7 +7319,7 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe)
* "yuv_scale_binary".
*/
need_isp_copy_binary =
- (pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_YUV422_8);
+ (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8);
#else /* !USE_INPUT_SYSTEM_VERSION_2401 */
need_isp_copy_binary = true;
#endif /* USE_INPUT_SYSTEM_VERSION_2401 */
@@ -7627,11 +7627,11 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
* Bayer-Quad RAW.
*/
int in_frame_format;
- if (pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY) {
+ if (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) {
in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8;
- } else if (pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_YUV422_8) {
+ } else if (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8) {
/*
- * When the sensor output frame format is "IA_CSS_STREAM_FORMAT_YUV422_8",
+ * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8",
* the "isp_copy_var" binary is selected as the first stage in the yuvpp
* pipe.
*
@@ -7739,7 +7739,7 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
for (i = 0, j = 0; i < num_stage; i++) {
assert(j < num_output_stage);
- if (pipe->pipe_settings.yuvpp.is_output_stage[i] == true) {
+ if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
tmp_out_frame = out_frame[j];
tmp_vf_frame = vf_frame[j];
} else {
@@ -7758,7 +7758,7 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
}
/* we use output port 1 as internal output port */
tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
- if (pipe->pipe_settings.yuvpp.is_output_stage[i] == true) {
+ if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) {
in_frame = yuv_scaler_stage->args.out_vf_frame;
err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j],
@@ -7812,7 +7812,7 @@ create_host_copy_pipeline(struct ia_css_pipe *pipe,
out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
if (copy_on_sp(pipe) &&
- pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_BINARY_8) {
+ pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
ia_css_frame_info_init(
&out_frame->info,
JPEG_BYTES,
@@ -8044,7 +8044,6 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
}
if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
- unsigned int frm;
struct ia_css_frame *local_in_frame = NULL;
struct ia_css_frame *local_out_frame = NULL;
@@ -8082,7 +8081,6 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
return err;
}
}
- (void)frm;
/* If we use copy iso primary,
the input must be yuv iso raw */
current_stage->args.copy_vf =
@@ -8321,8 +8319,6 @@ sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
struct ia_css_frame_info *info,
unsigned int idx)
{
- enum ia_css_err err = IA_CSS_SUCCESS;
-
assert(pipe != NULL);
assert(info != NULL);
@@ -8331,7 +8327,7 @@ sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
*info = pipe->output_info[idx];
if (copy_on_sp(pipe) &&
- pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_BINARY_8) {
+ pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
ia_css_frame_info_init(
info,
JPEG_BYTES,
@@ -8347,7 +8343,7 @@ sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
"sh_css_pipe_get_output_frame_info() leave:\n");
- return err;
+ return IA_CSS_SUCCESS;
}
#if !defined(HAS_NO_INPUT_SYSTEM)
@@ -8392,7 +8388,7 @@ ia_css_stream_send_input_line(const struct ia_css_stream *stream,
void
ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
- enum ia_css_stream_format format,
+ enum atomisp_input_format format,
const unsigned short *data,
unsigned int width)
{
@@ -9176,7 +9172,7 @@ ia_css_stream_configure_rx(struct ia_css_stream *stream)
else if (config->num_lanes != 0)
return IA_CSS_ERR_INVALID_ARGUMENTS;
- if (config->port > IA_CSS_CSI2_PORT2)
+ if (config->port > MIPI_PORT2_ID)
return IA_CSS_ERR_INVALID_ARGUMENTS;
stream->csi_rx_config.port =
ia_css_isys_port_to_mipi_port(config->port);
@@ -9363,7 +9359,7 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config,
#if defined(USE_INPUT_SYSTEM_VERSION_2)
/* We don't support metadata for JPEG stream, since they both use str2mem */
- if (stream_config->input_config.format == IA_CSS_STREAM_FORMAT_BINARY_8 &&
+ if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
stream_config->metadata_config.resolution.height > 0) {
err = IA_CSS_ERR_INVALID_ARGUMENTS;
IA_CSS_LEAVE_ERR(err);
@@ -10142,7 +10138,7 @@ ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe, enum ia_css_pipe_id
return IA_CSS_SUCCESS;
}
-enum ia_css_stream_format
+enum atomisp_input_format
ia_css_stream_get_format(const struct ia_css_stream *stream)
{
return stream->config.input_config.format;
@@ -10218,8 +10214,6 @@ ia_css_stream_get_3a_binary(const struct ia_css_stream *stream)
enum ia_css_err
ia_css_stream_set_output_padded_width(struct ia_css_stream *stream, unsigned int output_padded_width)
{
- enum ia_css_err err = IA_CSS_SUCCESS;
-
struct ia_css_pipe *pipe;
assert(stream != NULL);
@@ -10232,7 +10226,7 @@ ia_css_stream_set_output_padded_width(struct ia_css_stream *stream, unsigned int
pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
- return err;
+ return IA_CSS_SUCCESS;
}
static struct ia_css_binary *
@@ -10734,7 +10728,7 @@ ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, bool
(uint8_t) IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE,
(uint8_t) thread_id,
(uint8_t) stage->stage_num,
- (enable == true) ? 1 : 0);
+ enable ? 1 : 0);
if (err == IA_CSS_SUCCESS) {
if(enable)
SH_CSS_QOS_STAGE_ENABLE(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num);
@@ -11059,7 +11053,7 @@ static struct sh_css_hmm_buffer_record
buffer_record = &hmm_buffer_record[0];
for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
- if (buffer_record->in_use == false) {
+ if (!buffer_record->in_use) {
buffer_record->in_use = true;
buffer_record->type = type;
buffer_record->h_vbuf = h_vbuf;
@@ -11083,7 +11077,7 @@ static struct sh_css_hmm_buffer_record
buffer_record = &hmm_buffer_record[0];
for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
- if ((buffer_record->in_use == true) &&
+ if ((buffer_record->in_use) &&
(buffer_record->type == type) &&
(buffer_record->h_vbuf != NULL) &&
(buffer_record->h_vbuf->vptr == ddr_buffer_addr)) {
@@ -11093,7 +11087,7 @@ static struct sh_css_hmm_buffer_record
buffer_record++;
}
- if (found_record == true)
+ if (found_record)
return buffer_record;
else
return NULL;
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_mipi.c
index 883474e90c81..a6a00024bae8 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_mipi.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_mipi.c
@@ -104,7 +104,7 @@ static bool ia_css_mipi_is_source_port_valid(struct ia_css_pipe *pipe,
enum ia_css_err
ia_css_mipi_frame_calculate_size(const unsigned int width,
const unsigned int height,
- const enum ia_css_stream_format format,
+ const enum atomisp_input_format format,
const bool hasSOLandEOL,
const unsigned int embedded_data_size_words,
unsigned int *size_mem_words)
@@ -136,16 +136,16 @@ ia_css_mipi_frame_calculate_size(const unsigned int width,
width_padded, height, format, hasSOLandEOL, embedded_data_size_words);
switch (format) {
- case IA_CSS_STREAM_FORMAT_RAW_6: /* 4p, 3B, 24bits */
+ case ATOMISP_INPUT_FORMAT_RAW_6: /* 4p, 3B, 24bits */
bits_per_pixel = 6; break;
- case IA_CSS_STREAM_FORMAT_RAW_7: /* 8p, 7B, 56bits */
+ case ATOMISP_INPUT_FORMAT_RAW_7: /* 8p, 7B, 56bits */
bits_per_pixel = 7; break;
- case IA_CSS_STREAM_FORMAT_RAW_8: /* 1p, 1B, 8bits */
- case IA_CSS_STREAM_FORMAT_BINARY_8: /* 8bits, TODO: check. */
- case IA_CSS_STREAM_FORMAT_YUV420_8: /* odd 2p, 2B, 16bits, even 2p, 4B, 32bits */
+ case ATOMISP_INPUT_FORMAT_RAW_8: /* 1p, 1B, 8bits */
+ case ATOMISP_INPUT_FORMAT_BINARY_8: /* 8bits, TODO: check. */
+ case ATOMISP_INPUT_FORMAT_YUV420_8: /* odd 2p, 2B, 16bits, even 2p, 4B, 32bits */
bits_per_pixel = 8; break;
- case IA_CSS_STREAM_FORMAT_YUV420_10: /* odd 4p, 5B, 40bits, even 4p, 10B, 80bits */
- case IA_CSS_STREAM_FORMAT_RAW_10: /* 4p, 5B, 40bits */
+ case ATOMISP_INPUT_FORMAT_YUV420_10: /* odd 4p, 5B, 40bits, even 4p, 10B, 80bits */
+ case ATOMISP_INPUT_FORMAT_RAW_10: /* 4p, 5B, 40bits */
#if !defined(HAS_NO_PACKED_RAW_PIXELS)
/* The changes will be reverted as soon as RAW
* Buffers are deployed by the 2401 Input System
@@ -156,26 +156,26 @@ ia_css_mipi_frame_calculate_size(const unsigned int width,
bits_per_pixel = 16;
#endif
break;
- case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY: /* 2p, 3B, 24bits */
- case IA_CSS_STREAM_FORMAT_RAW_12: /* 2p, 3B, 24bits */
+ case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: /* 2p, 3B, 24bits */
+ case ATOMISP_INPUT_FORMAT_RAW_12: /* 2p, 3B, 24bits */
bits_per_pixel = 12; break;
- case IA_CSS_STREAM_FORMAT_RAW_14: /* 4p, 7B, 56bits */
+ case ATOMISP_INPUT_FORMAT_RAW_14: /* 4p, 7B, 56bits */
bits_per_pixel = 14; break;
- case IA_CSS_STREAM_FORMAT_RGB_444: /* 1p, 2B, 16bits */
- case IA_CSS_STREAM_FORMAT_RGB_555: /* 1p, 2B, 16bits */
- case IA_CSS_STREAM_FORMAT_RGB_565: /* 1p, 2B, 16bits */
- case IA_CSS_STREAM_FORMAT_YUV422_8: /* 2p, 4B, 32bits */
+ case ATOMISP_INPUT_FORMAT_RGB_444: /* 1p, 2B, 16bits */
+ case ATOMISP_INPUT_FORMAT_RGB_555: /* 1p, 2B, 16bits */
+ case ATOMISP_INPUT_FORMAT_RGB_565: /* 1p, 2B, 16bits */
+ case ATOMISP_INPUT_FORMAT_YUV422_8: /* 2p, 4B, 32bits */
bits_per_pixel = 16; break;
- case IA_CSS_STREAM_FORMAT_RGB_666: /* 4p, 9B, 72bits */
+ case ATOMISP_INPUT_FORMAT_RGB_666: /* 4p, 9B, 72bits */
bits_per_pixel = 18; break;
- case IA_CSS_STREAM_FORMAT_YUV422_10: /* 2p, 5B, 40bits */
+ case ATOMISP_INPUT_FORMAT_YUV422_10: /* 2p, 5B, 40bits */
bits_per_pixel = 20; break;
- case IA_CSS_STREAM_FORMAT_RGB_888: /* 1p, 3B, 24bits */
+ case ATOMISP_INPUT_FORMAT_RGB_888: /* 1p, 3B, 24bits */
bits_per_pixel = 24; break;
- case IA_CSS_STREAM_FORMAT_YUV420_16: /* Not supported */
- case IA_CSS_STREAM_FORMAT_YUV422_16: /* Not supported */
- case IA_CSS_STREAM_FORMAT_RAW_16: /* TODO: not specified in MIPI SPEC, check */
+ case ATOMISP_INPUT_FORMAT_YUV420_16: /* Not supported */
+ case ATOMISP_INPUT_FORMAT_YUV422_16: /* Not supported */
+ case ATOMISP_INPUT_FORMAT_RAW_16: /* TODO: not specified in MIPI SPEC, check */
default:
return IA_CSS_ERR_INVALID_ARGUMENTS;
}
@@ -183,9 +183,9 @@ ia_css_mipi_frame_calculate_size(const unsigned int width,
odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
/* Even lines for YUV420 formats are double in bits_per_pixel. */
- if (format == IA_CSS_STREAM_FORMAT_YUV420_8
- || format == IA_CSS_STREAM_FORMAT_YUV420_10
- || format == IA_CSS_STREAM_FORMAT_YUV420_16) {
+ if (format == ATOMISP_INPUT_FORMAT_YUV420_8
+ || format == ATOMISP_INPUT_FORMAT_YUV420_10
+ || format == ATOMISP_INPUT_FORMAT_YUV420_16) {
even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
} else {
even_line_bytes = odd_line_bytes;
@@ -239,7 +239,7 @@ ia_css_mipi_frame_calculate_size(const unsigned int width,
#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
enum ia_css_err
-ia_css_mipi_frame_enable_check_on_size(const enum ia_css_csi2_port port,
+ia_css_mipi_frame_enable_check_on_size(const enum mipi_port_id port,
const unsigned int size_mem_words)
{
uint32_t idx;
@@ -285,7 +285,7 @@ calculate_mipi_buff_size(
#else
unsigned int width;
unsigned int height;
- enum ia_css_stream_format format;
+ enum atomisp_input_format format;
bool pack_raw_pixels;
unsigned int width_padded;
@@ -348,15 +348,15 @@ calculate_mipi_buff_size(
bits_per_pixel = sh_css_stream_format_2_bits_per_subpixel(format);
bits_per_pixel =
- (format == IA_CSS_STREAM_FORMAT_RAW_10 && pack_raw_pixels) ? bits_per_pixel : 16;
+ (format == ATOMISP_INPUT_FORMAT_RAW_10 && pack_raw_pixels) ? bits_per_pixel : 16;
if (bits_per_pixel == 0)
return IA_CSS_ERR_INTERNAL_ERROR;
odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
/* Even lines for YUV420 formats are double in bits_per_pixel. */
- if (format == IA_CSS_STREAM_FORMAT_YUV420_8
- || format == IA_CSS_STREAM_FORMAT_YUV420_10) {
+ if (format == ATOMISP_INPUT_FORMAT_YUV420_8
+ || format == ATOMISP_INPUT_FORMAT_YUV420_10) {
even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
} else {
even_line_bytes = odd_line_bytes;
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_params.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_params.c
index fbb36112fe3c..43529b1605c3 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_params.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_params.c
@@ -110,7 +110,7 @@
#define FPNTBL_BYTES(binary) \
(sizeof(char) * (binary)->in_frame_info.res.height * \
(binary)->in_frame_info.padded_width)
-
+
#ifndef ISP2401
#define SCTBL_BYTES(binary) \
@@ -1741,7 +1741,7 @@ ia_css_process_zoom_and_motion(
out_infos[0] = &args->out_frame[0]->info;
info = &stage->firmware->info.isp;
ia_css_binary_fill_info(info, false, false,
- IA_CSS_STREAM_FORMAT_RAW_10,
+ ATOMISP_INPUT_FORMAT_RAW_10,
args->in_frame ? &args->in_frame->info : NULL,
NULL,
out_infos,
@@ -2891,8 +2891,8 @@ ia_css_metadata_free_multiple(unsigned int num_bufs, struct ia_css_metadata **bu
}
}
-unsigned g_param_buffer_dequeue_count = 0;
-unsigned g_param_buffer_enqueue_count = 0;
+static unsigned g_param_buffer_dequeue_count = 0;
+static unsigned g_param_buffer_enqueue_count = 0;
enum ia_css_err
ia_css_stream_isp_parameters_init(struct ia_css_stream *stream)
@@ -3805,7 +3805,6 @@ sh_css_param_update_isp_params(struct ia_css_pipe *curr_pipe,
enum sh_css_queue_id queue_id;
- (void)stage;
pipe = curr_pipe->stream->pipes[i];
pipeline = ia_css_pipe_get_pipeline(pipe);
pipe_num = ia_css_pipe_get_pipe_num(pipe);
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_sp.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_sp.c
index 6fc00fc402b1..85263725540d 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_sp.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_sp.c
@@ -71,7 +71,7 @@
struct sh_css_sp_group sh_css_sp_group;
struct sh_css_sp_stage sh_css_sp_stage;
struct sh_css_isp_stage sh_css_isp_stage;
-struct sh_css_sp_output sh_css_sp_output;
+static struct sh_css_sp_output sh_css_sp_output;
static struct sh_css_sp_per_frame_data per_frame_data;
/* true if SP supports frame loop and host2sp_commands */
@@ -117,9 +117,9 @@ copy_isp_stage_to_sp_stage(void)
*/
sh_css_sp_stage.enable.sdis = sh_css_isp_stage.binary_info.enable.dis;
sh_css_sp_stage.enable.s3a = sh_css_isp_stage.binary_info.enable.s3a;
-#ifdef ISP2401
+#ifdef ISP2401
sh_css_sp_stage.enable.lace_stats = sh_css_isp_stage.binary_info.enable.lace_stats;
-#endif
+#endif
}
void
@@ -754,7 +754,7 @@ sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args)
static void
sh_css_sp_init_group(bool two_ppc,
- enum ia_css_stream_format input_format,
+ enum atomisp_input_format input_format,
bool no_isp_sync,
uint8_t if_config_index)
{
@@ -817,7 +817,6 @@ configure_isp_from_args(
bool two_ppc,
bool deinterleaved)
{
- enum ia_css_err err = IA_CSS_SUCCESS;
#ifdef ISP2401
struct ia_css_pipe *pipe = find_pipe_by_num(pipeline->pipe_num);
const struct ia_css_resolution *res;
@@ -841,7 +840,7 @@ configure_isp_from_args(
ia_css_ref_configure(binary, (const struct ia_css_frame **)args->delay_frames, pipeline->dvs_frame_delay);
ia_css_tnr_configure(binary, (const struct ia_css_frame **)args->tnr_frames);
ia_css_bayer_io_config(binary, args);
- return err;
+ return IA_CSS_SUCCESS;
}
static void
@@ -1118,7 +1117,7 @@ sp_init_stage(struct ia_css_pipeline_stage *stage,
out_infos[0] = &args->out_frame[0]->info;
info = &firmware->info.isp;
ia_css_binary_fill_info(info, false, false,
- IA_CSS_STREAM_FORMAT_RAW_10,
+ ATOMISP_INPUT_FORMAT_RAW_10,
args->in_frame ? &args->in_frame->info : NULL,
NULL,
out_infos,
@@ -1197,7 +1196,7 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
const struct ia_css_metadata_config *md_config,
const struct ia_css_metadata_info *md_info,
#if !defined(HAS_NO_INPUT_SYSTEM)
- const mipi_port_ID_t port_id
+ const enum mipi_port_id port_id
#endif
#ifdef ISP2401
,
@@ -1442,8 +1441,6 @@ sh_css_update_host2sp_offline_frame(
unsigned int HIVE_ADDR_host_sp_com;
unsigned int offset;
- (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
-
assert(frame_num < NUM_CONTINUOUS_FRAMES);
/* Write new frame data into SP DMEM */
@@ -1473,8 +1470,6 @@ sh_css_update_host2sp_mipi_frame(
unsigned int HIVE_ADDR_host_sp_com;
unsigned int offset;
- (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
-
/* MIPI buffers are dedicated to port, so now there are more of them. */
assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
@@ -1500,8 +1495,6 @@ sh_css_update_host2sp_mipi_metadata(
unsigned int HIVE_ADDR_host_sp_com;
unsigned int o;
- (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
-
/* MIPI buffers are dedicated to port, so now there are more of them. */
assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
@@ -1520,8 +1513,6 @@ sh_css_update_host2sp_num_mipi_frames(unsigned num_frames)
unsigned int HIVE_ADDR_host_sp_com;
unsigned int offset;
- (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
-
/* Write new frame data into SP DMEM */
HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_num_mipi_frames)
@@ -1539,8 +1530,6 @@ sh_css_update_host2sp_cont_num_raw_frames(unsigned num_frames, bool set_avail)
unsigned int extra_num_frames, avail_num_frames;
unsigned int offset, offset_extra;
- (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
-
/* Write new frame data into SP DMEM */
fw = &sh_css_sp_fw;
HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_sp.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_sp.h
index 98444a3cc3e4..3c41e997de79 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_sp.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_sp.h
@@ -64,7 +64,7 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
const struct ia_css_metadata_config *md_config,
const struct ia_css_metadata_info *md_info,
#if !defined(HAS_NO_INPUT_SYSTEM)
- const mipi_port_ID_t port_id
+ const enum mipi_port_id port_id
#endif
#ifdef ISP2401
,
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_stream_format.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_stream_format.c
index 52d0a6471597..77f135e7dc3c 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_stream_format.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_stream_format.c
@@ -16,55 +16,55 @@
#include <ia_css_stream_format.h>
unsigned int sh_css_stream_format_2_bits_per_subpixel(
- enum ia_css_stream_format format)
+ enum atomisp_input_format format)
{
unsigned int rval;
switch (format) {
- case IA_CSS_STREAM_FORMAT_RGB_444:
+ case ATOMISP_INPUT_FORMAT_RGB_444:
rval = 4;
break;
- case IA_CSS_STREAM_FORMAT_RGB_555:
+ case ATOMISP_INPUT_FORMAT_RGB_555:
rval = 5;
break;
- case IA_CSS_STREAM_FORMAT_RGB_565:
- case IA_CSS_STREAM_FORMAT_RGB_666:
- case IA_CSS_STREAM_FORMAT_RAW_6:
+ case ATOMISP_INPUT_FORMAT_RGB_565:
+ case ATOMISP_INPUT_FORMAT_RGB_666:
+ case ATOMISP_INPUT_FORMAT_RAW_6:
rval = 6;
break;
- case IA_CSS_STREAM_FORMAT_RAW_7:
+ case ATOMISP_INPUT_FORMAT_RAW_7:
rval = 7;
break;
- case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
- case IA_CSS_STREAM_FORMAT_YUV420_8:
- case IA_CSS_STREAM_FORMAT_YUV422_8:
- case IA_CSS_STREAM_FORMAT_RGB_888:
- case IA_CSS_STREAM_FORMAT_RAW_8:
- case IA_CSS_STREAM_FORMAT_BINARY_8:
- case IA_CSS_STREAM_FORMAT_USER_DEF1:
- case IA_CSS_STREAM_FORMAT_USER_DEF2:
- case IA_CSS_STREAM_FORMAT_USER_DEF3:
- case IA_CSS_STREAM_FORMAT_USER_DEF4:
- case IA_CSS_STREAM_FORMAT_USER_DEF5:
- case IA_CSS_STREAM_FORMAT_USER_DEF6:
- case IA_CSS_STREAM_FORMAT_USER_DEF7:
- case IA_CSS_STREAM_FORMAT_USER_DEF8:
+ case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
+ case ATOMISP_INPUT_FORMAT_YUV420_8:
+ case ATOMISP_INPUT_FORMAT_YUV422_8:
+ case ATOMISP_INPUT_FORMAT_RGB_888:
+ case ATOMISP_INPUT_FORMAT_RAW_8:
+ case ATOMISP_INPUT_FORMAT_BINARY_8:
+ case ATOMISP_INPUT_FORMAT_USER_DEF1:
+ case ATOMISP_INPUT_FORMAT_USER_DEF2:
+ case ATOMISP_INPUT_FORMAT_USER_DEF3:
+ case ATOMISP_INPUT_FORMAT_USER_DEF4:
+ case ATOMISP_INPUT_FORMAT_USER_DEF5:
+ case ATOMISP_INPUT_FORMAT_USER_DEF6:
+ case ATOMISP_INPUT_FORMAT_USER_DEF7:
+ case ATOMISP_INPUT_FORMAT_USER_DEF8:
rval = 8;
break;
- case IA_CSS_STREAM_FORMAT_YUV420_10:
- case IA_CSS_STREAM_FORMAT_YUV422_10:
- case IA_CSS_STREAM_FORMAT_RAW_10:
+ case ATOMISP_INPUT_FORMAT_YUV420_10:
+ case ATOMISP_INPUT_FORMAT_YUV422_10:
+ case ATOMISP_INPUT_FORMAT_RAW_10:
rval = 10;
break;
- case IA_CSS_STREAM_FORMAT_RAW_12:
+ case ATOMISP_INPUT_FORMAT_RAW_12:
rval = 12;
break;
- case IA_CSS_STREAM_FORMAT_RAW_14:
+ case ATOMISP_INPUT_FORMAT_RAW_14:
rval = 14;
break;
- case IA_CSS_STREAM_FORMAT_RAW_16:
- case IA_CSS_STREAM_FORMAT_YUV420_16:
- case IA_CSS_STREAM_FORMAT_YUV422_16:
+ case ATOMISP_INPUT_FORMAT_RAW_16:
+ case ATOMISP_INPUT_FORMAT_YUV420_16:
+ case ATOMISP_INPUT_FORMAT_YUV422_16:
rval = 16;
break;
default:
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_stream_format.h b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_stream_format.h
index aab2b6207051..b699f538e0dd 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_stream_format.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css_stream_format.h
@@ -18,6 +18,6 @@
#include <ia_css_stream_format.h>
unsigned int sh_css_stream_format_2_bits_per_subpixel(
- enum ia_css_stream_format format);
+ enum atomisp_input_format format);
#endif /* __SH_CSS_STREAM_FORMAT_H */
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/include/mmu/isp_mmu.h b/drivers/staging/media/atomisp/pci/atomisp2/include/mmu/isp_mmu.h
index 560014add005..4b2d94a37ea1 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/include/mmu/isp_mmu.h
+++ b/drivers/staging/media/atomisp/pci/atomisp2/include/mmu/isp_mmu.h
@@ -80,12 +80,10 @@ struct isp_mmu_client {
unsigned int null_pte;
/*
- * set/get page directory base address (physical address).
+ * get page directory base address (physical address).
*
* must be provided.
*/
- int (*set_pd_base) (struct isp_mmu *mmu,
- phys_addr_t pd_base);
unsigned int (*get_pd_base) (struct isp_mmu *mmu, phys_addr_t pd_base);
/*
* callback to flush tlb.
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/mmu/isp_mmu.c b/drivers/staging/media/atomisp/pci/atomisp2/mmu/isp_mmu.c
index f21075c1e503..198f29f4a324 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/mmu/isp_mmu.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/mmu/isp_mmu.c
@@ -344,13 +344,6 @@ static int mmu_map(struct isp_mmu *mmu, unsigned int isp_virt,
/*
* setup L1 page table physical addr to MMU
*/
- ret = mmu->driver->set_pd_base(mmu, l1_pt);
- if (ret) {
- dev_err(atomisp_dev,
- "set page directory base address fail.\n");
- mutex_unlock(&mmu->pt_mutex);
- return ret;
- }
mmu->base_address = l1_pt;
mmu->l1_pte = isp_pgaddr_to_pte_valid(mmu, l1_pt);
memset(mmu->l2_pgt_refcount, 0, sizeof(int) * ISP_L1PT_PTES);
@@ -531,10 +524,8 @@ int isp_mmu_init(struct isp_mmu *mmu, struct isp_mmu_client *driver)
mmu->driver = driver;
- if (!driver->set_pd_base || !driver->tlb_flush_all) {
- dev_err(atomisp_dev,
- "set_pd_base or tlb_flush_all operation "
- "not provided.\n");
+ if (!driver->tlb_flush_all) {
+ dev_err(atomisp_dev, "tlb_flush_all operation not provided.\n");
return -EINVAL;
}
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/mmu/sh_mmu_mrfld.c b/drivers/staging/media/atomisp/pci/atomisp2/mmu/sh_mmu_mrfld.c
index c59bcc982966..c0212564b7c8 100644
--- a/drivers/staging/media/atomisp/pci/atomisp2/mmu/sh_mmu_mrfld.c
+++ b/drivers/staging/media/atomisp/pci/atomisp2/mmu/sh_mmu_mrfld.c
@@ -18,6 +18,7 @@
*/
#include "type_support.h"
#include "mmu/isp_mmu.h"
+#include "mmu/sh_mmu_mrfld.h"
#include "memory_access/memory_access.h"
#include "atomisp_compat.h"
@@ -40,20 +41,6 @@ static phys_addr_t sh_pte_to_phys(struct isp_mmu *mmu,
return (phys_addr_t)((pte & ~mask) << ISP_PAGE_OFFSET);
}
-/*
- * set page directory base address (physical address).
- *
- * must be provided.
- */
-static int sh_set_pd_base(struct isp_mmu *mmu,
- phys_addr_t phys)
-{
- unsigned int pte = sh_phys_to_pte(mmu, phys);
- /*mmgr_set_base_address(HOST_ADDRESS(pte));*/
- atomisp_css_mmu_set_page_table_base_index(HOST_ADDRESS(pte));
- return 0;
-}
-
static unsigned int sh_get_pd_base(struct isp_mmu *mmu,
phys_addr_t phys)
{
@@ -81,7 +68,6 @@ struct isp_mmu_client sh_mmu_mrfld = {
.name = "Silicon Hive ISP3000 MMU",
.pte_valid_mask = MERR_VALID_PTE_MASK,
.null_pte = ~MERR_VALID_PTE_MASK,
- .set_pd_base = sh_set_pd_base,
.get_pd_base = sh_get_pd_base,
.tlb_flush_all = sh_tlb_flush,
.phys_to_pte = sh_phys_to_pte,
diff --git a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
index d8b7183db252..3283c1b05d6a 100644
--- a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
+++ b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
@@ -441,7 +441,7 @@ static int gmin_v1p2_ctrl(struct v4l2_subdev *subdev, int on)
{
struct gmin_subdev *gs = find_gmin_subdev(subdev);
- if (gs && gs->v1p2_on == on)
+ if (!gs || gs->v1p2_on == on)
return 0;
gs->v1p2_on = on;
@@ -475,7 +475,7 @@ static int gmin_v1p8_ctrl(struct v4l2_subdev *subdev, int on)
}
}
- if (gs && gs->v1p8_on == on)
+ if (!gs || gs->v1p8_on == on)
return 0;
gs->v1p8_on = on;
@@ -511,7 +511,7 @@ static int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on)
}
}
- if (gs && gs->v2p8_on == on)
+ if (!gs || gs->v2p8_on == on)
return 0;
gs->v2p8_on = on;
@@ -693,9 +693,11 @@ static int gmin_get_config_var(struct device *dev, const char *var,
for (i = 0; i < sizeof(var8) && var8[i]; i++)
var16[i] = var8[i];
+#ifdef CONFIG_64BIT
/* To avoid owerflows when calling the efivar API */
if (*out_len > ULONG_MAX)
return -EINVAL;
+#endif
/* Not sure this API usage is kosher; efivar_entry_get()'s
* implementation simply uses VariableName and VendorGuid from
diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
index 857b0e847c5e..1ee216d71d42 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
@@ -480,7 +480,7 @@ resizer_configure_common_in_params(struct vpfe_resizer_device *resizer)
return 0;
}
static int
-resizer_configure_in_continious_mode(struct vpfe_resizer_device *resizer)
+resizer_configure_in_continuous_mode(struct vpfe_resizer_device *resizer)
{
struct device *dev = resizer->crop_resizer.subdev.v4l2_dev->dev;
struct resizer_params *param = &resizer->config;
@@ -1242,7 +1242,7 @@ static int resizer_do_hw_setup(struct vpfe_resizer_device *resizer)
ipipeif_source == IPIPEIF_OUTPUT_RESIZER)
ret = resizer_configure_in_single_shot_mode(resizer);
else
- ret = resizer_configure_in_continious_mode(resizer);
+ ret = resizer_configure_in_continuous_mode(resizer);
if (ret)
return ret;
ret = config_rsz_hw(resizer, param);
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 1aa2be891704..16cab40156ca 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1005,7 +1005,7 @@ static int csi_link_validate(struct v4l2_subdev *sd,
struct v4l2_subdev_format *sink_fmt)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
- struct v4l2_fwnode_endpoint upstream_ep;
+ struct v4l2_fwnode_endpoint upstream_ep = {};
const struct imx_media_pixfmt *incc;
bool is_csi2;
int ret;
@@ -1800,7 +1800,10 @@ static int imx_csi_probe(struct platform_device *pdev)
pinctrl = devm_pinctrl_get_select_default(priv->dev);
if (IS_ERR(pinctrl)) {
ret = PTR_ERR(priv->vdev);
- goto free;
+ dev_dbg(priv->dev,
+ "devm_pinctrl_get_select_default() failed: %d\n", ret);
+ if (ret != -ENODEV)
+ goto free;
}
ret = v4l2_async_register_subdev(&priv->sd);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4f950c686055..83d3d271ca15 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -9,9 +9,6 @@ if HAS_IOMEM
config HAVE_FB_ATMEL
bool
-config SH_LCD_MIPI_DSI
- bool
-
source "drivers/char/agp/Kconfig"
source "drivers/gpu/vga/Kconfig"
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index d1d3796773aa..08b822656846 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -827,10 +827,8 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address,
}
sti = kzalloc(sizeof(*sti), GFP_KERNEL);
- if (!sti) {
- printk(KERN_ERR "Not enough memory !\n");
+ if (!sti)
return NULL;
- }
spin_lock_init(&sti->lock);
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 399573742487..d94254263ea5 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -1053,6 +1053,11 @@ config FB_I810_I2C
bool "Enable DDC Support"
depends on FB_I810 && FB_I810_GTF
select FB_DDC
+ help
+ Add DDC/I2C support for i810fb. This will allow the driver to get
+ display information, especially for monitors with fickle timings.
+
+ If unsure, say Y.
config FB_LE80578
tristate "Intel LE80578 (Vermilion) support"
@@ -1917,8 +1922,7 @@ config FB_TMIO_ACCELL
config FB_S3C
tristate "Samsung S3C framebuffer support"
- depends on FB && (CPU_S3C2416 || ARCH_S3C64XX || \
- ARCH_S5PV210 || ARCH_EXYNOS)
+ depends on FB && (CPU_S3C2416 || ARCH_S3C64XX)
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/fbdev/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c
index 36d25190b48c..38c1f324ce15 100644
--- a/drivers/video/fbdev/amba-clcd.c
+++ b/drivers/video/fbdev/amba-clcd.c
@@ -967,9 +967,8 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
goto out;
}
- fb = kzalloc(sizeof(struct clcd_fb), GFP_KERNEL);
+ fb = kzalloc(sizeof(*fb), GFP_KERNEL);
if (!fb) {
- printk(KERN_INFO "CLCD: could not allocate new clcd_fb struct\n");
ret = -ENOMEM;
goto free_region;
}
diff --git a/drivers/video/fbdev/atmel_lcdfb.c b/drivers/video/fbdev/atmel_lcdfb.c
index 3dee267d7c75..076d24afbd72 100644
--- a/drivers/video/fbdev/atmel_lcdfb.c
+++ b/drivers/video/fbdev/atmel_lcdfb.c
@@ -18,10 +18,10 @@
#include <linux/delay.h>
#include <linux/backlight.h>
#include <linux/gfp.h>
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <video/of_display_timing.h>
#include <linux/regulator/consumer.h>
#include <video/videomode.h>
@@ -61,8 +61,7 @@ struct atmel_lcdfb_info {
};
struct atmel_lcdfb_power_ctrl_gpio {
- int gpio;
- int active_low;
+ struct gpio_desc *gpiod;
struct list_head list;
};
@@ -1018,7 +1017,7 @@ static void atmel_lcdfb_power_control_gpio(struct atmel_lcdfb_pdata *pdata, int
struct atmel_lcdfb_power_ctrl_gpio *og;
list_for_each_entry(og, &pdata->pwr_gpios, list)
- gpio_set_value(og->gpio, on);
+ gpiod_set_value(og->gpiod, on);
}
static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
@@ -1031,11 +1030,11 @@ static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
struct device_node *display_np;
struct device_node *timings_np;
struct display_timings *timings;
- enum of_gpio_flags flags;
struct atmel_lcdfb_power_ctrl_gpio *og;
bool is_gpio_power = false;
+ struct gpio_desc *gpiod;
int ret = -ENOENT;
- int i, gpio;
+ int i;
sinfo->config = (struct atmel_lcdfb_config*)
of_match_device(atmel_lcdfb_dt_ids, dev)->data;
@@ -1072,28 +1071,22 @@ static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
INIT_LIST_HEAD(&pdata->pwr_gpios);
ret = -ENOMEM;
- for (i = 0; i < of_gpio_named_count(display_np, "atmel,power-control-gpio"); i++) {
- gpio = of_get_named_gpio_flags(display_np, "atmel,power-control-gpio",
- i, &flags);
- if (gpio < 0)
+ for (i = 0; i < gpiod_count(dev, "atmel,power-control"); i++) {
+ gpiod = devm_gpiod_get_index(dev, "atmel,power-control",
+ i, GPIOD_ASIS);
+ if (IS_ERR(gpiod))
continue;
og = devm_kzalloc(dev, sizeof(*og), GFP_KERNEL);
if (!og)
goto put_display_node;
- og->gpio = gpio;
- og->active_low = flags & OF_GPIO_ACTIVE_LOW;
+ og->gpiod = gpiod;
is_gpio_power = true;
- ret = devm_gpio_request(dev, gpio, "lcd-power-control-gpio");
- if (ret) {
- dev_err(dev, "request gpio %d failed\n", gpio);
- goto put_display_node;
- }
- ret = gpio_direction_output(gpio, og->active_low);
+ ret = gpiod_direction_output(gpiod, gpiod_is_active_low(gpiod));
if (ret) {
- dev_err(dev, "set direction output gpio %d failed\n", gpio);
+ dev_err(dev, "set direction output gpio atmel,power-control[%d] failed\n", i);
goto put_display_node;
}
list_add(&og->list, &pdata->pwr_gpios);
diff --git a/drivers/video/fbdev/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c
index db18474607c9..09b0e558dce8 100644
--- a/drivers/video/fbdev/aty/aty128fb.c
+++ b/drivers/video/fbdev/aty/aty128fb.c
@@ -1716,7 +1716,7 @@ static int aty128fb_setup(char *options)
continue;
}
if(!strncmp(this_opt, "nomtrr", 6)) {
- mtrr = 0;
+ mtrr = false;
continue;
}
#ifdef CONFIG_PPC_PMAC
diff --git a/drivers/video/fbdev/aty/mach64_ct.c b/drivers/video/fbdev/aty/mach64_ct.c
index 7d3bd723d3d5..74a62aa193c0 100644
--- a/drivers/video/fbdev/aty/mach64_ct.c
+++ b/drivers/video/fbdev/aty/mach64_ct.c
@@ -180,7 +180,7 @@ static int aty_dsp_gt(const struct fb_info *info, u32 bpp, struct pll_ct *pll)
dsp_on = ((multiplier << vshift) + divider) / divider;
tmp = ((ras_multiplier << xshift) + ras_divider) / ras_divider;
if (dsp_on < tmp)
- dsp_on = tmp;
+ dsp_on = tmp;
dsp_on = dsp_on + (tmp * 2) + (pll->xclkpagefaultdelay << xshift);
}
diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c
index 87608c0b2351..e8594bbaea60 100644
--- a/drivers/video/fbdev/aty/radeon_base.c
+++ b/drivers/video/fbdev/aty/radeon_base.c
@@ -2255,6 +2255,23 @@ static const struct bin_attribute edid2_attr = {
.read = radeon_show_edid2,
};
+static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
+{
+ struct apertures_struct *ap;
+
+ ap = alloc_apertures(1);
+ if (!ap)
+ return -ENOMEM;
+
+ ap->ranges[0].base = pci_resource_start(pdev, 0);
+ ap->ranges[0].size = pci_resource_len(pdev, 0);
+
+ remove_conflicting_framebuffers(ap, KBUILD_MODNAME, false);
+
+ kfree(ap);
+
+ return 0;
+}
static int radeonfb_pci_register(struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -2308,6 +2325,10 @@ static int radeonfb_pci_register(struct pci_dev *pdev,
rinfo->fb_base_phys = pci_resource_start (pdev, 0);
rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
+ ret = radeon_kick_out_firmware_fb(pdev);
+ if (ret)
+ return ret;
+
/* request the mem regions */
ret = pci_request_region(pdev, 0, "radeonfb framebuffer");
if (ret < 0) {
diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c
index 8de42f617d16..7c9a672e9811 100644
--- a/drivers/video/fbdev/au1100fb.c
+++ b/drivers/video/fbdev/au1100fb.c
@@ -410,18 +410,15 @@ static int au1100fb_setup(struct au1100fb_device *fbdev)
static int au1100fb_drv_probe(struct platform_device *dev)
{
- struct au1100fb_device *fbdev = NULL;
+ struct au1100fb_device *fbdev;
struct resource *regs_res;
unsigned long page;
struct clk *c;
/* Allocate new device private */
- fbdev = devm_kzalloc(&dev->dev, sizeof(struct au1100fb_device),
- GFP_KERNEL);
- if (!fbdev) {
- print_err("fail to allocate device private record");
+ fbdev = devm_kzalloc(&dev->dev, sizeof(*fbdev), GFP_KERNEL);
+ if (!fbdev)
return -ENOMEM;
- }
if (au1100fb_setup(fbdev))
goto failed;
diff --git a/drivers/video/fbdev/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c
index 25abbcf38913..1bfd13cbd4e3 100644
--- a/drivers/video/fbdev/fsl-diu-fb.c
+++ b/drivers/video/fbdev/fsl-diu-fb.c
@@ -1960,12 +1960,8 @@ static int __init fsl_diu_init(void)
of_node_put(np);
coherence_data = vmalloc(coherence_data_size);
- if (!coherence_data) {
- pr_err("fsl-diu-fb: could not allocate coherence data "
- "(size=%zu)\n", coherence_data_size);
+ if (!coherence_data)
return -ENOMEM;
- }
-
#endif
ret = platform_driver_register(&fsl_diu_driver);
diff --git a/drivers/video/fbdev/matrox/matroxfb_crtc2.c b/drivers/video/fbdev/matrox/matroxfb_crtc2.c
index 02796a4317a9..f64e1d55d7a1 100644
--- a/drivers/video/fbdev/matrox/matroxfb_crtc2.c
+++ b/drivers/video/fbdev/matrox/matroxfb_crtc2.c
@@ -696,10 +696,9 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {
if (!minfo->devflags.crtc2)
return NULL;
m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
- if (!m2info) {
- printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n");
+ if (!m2info)
return NULL;
- }
+
m2info->primary_dev = minfo;
if (matroxfb_dh_registerfb(m2info)) {
kfree(m2info);
diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c
index 90d38de34479..77c0a2f45b3b 100644
--- a/drivers/video/fbdev/offb.c
+++ b/drivers/video/fbdev/offb.c
@@ -280,6 +280,7 @@ static void offb_destroy(struct fb_info *info)
if (info->screen_base)
iounmap(info->screen_base);
release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
+ fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
@@ -518,6 +519,7 @@ static void __init offb_init_fb(const char *name,
return;
out_err:
+ fb_dealloc_cmap(&info->cmap);
iounmap(info->screen_base);
out_aper:
iounmap(par->cmap_adr);
diff --git a/drivers/video/fbdev/s3c-fb.c b/drivers/video/fbdev/s3c-fb.c
index 5f4f696c2ecf..9ec85ccd0ce9 100644
--- a/drivers/video/fbdev/s3c-fb.c
+++ b/drivers/video/fbdev/s3c-fb.c
@@ -1383,11 +1383,9 @@ static int s3c_fb_probe(struct platform_device *pdev)
return -EINVAL;
}
- sfb = devm_kzalloc(dev, sizeof(struct s3c_fb), GFP_KERNEL);
- if (!sfb) {
- dev_err(dev, "no memory for framebuffers\n");
+ sfb = devm_kzalloc(dev, sizeof(*sfb), GFP_KERNEL);
+ if (!sfb)
return -ENOMEM;
- }
dev_dbg(dev, "allocate new framebuffer %p\n", sfb);
@@ -1716,63 +1714,6 @@ static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = {
},
};
-static struct s3c_fb_win_variant s3c_fb_data_s5p_wins[] = {
- [0] = {
- .has_osd_c = 1,
- .osd_size_off = 0x8,
- .palette_sz = 256,
- .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
- VALID_BPP(15) | VALID_BPP(16) |
- VALID_BPP(18) | VALID_BPP(19) |
- VALID_BPP(24) | VALID_BPP(25) |
- VALID_BPP(32)),
- },
- [1] = {
- .has_osd_c = 1,
- .has_osd_d = 1,
- .osd_size_off = 0xc,
- .has_osd_alpha = 1,
- .palette_sz = 256,
- .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
- VALID_BPP(15) | VALID_BPP(16) |
- VALID_BPP(18) | VALID_BPP(19) |
- VALID_BPP(24) | VALID_BPP(25) |
- VALID_BPP(32)),
- },
- [2] = {
- .has_osd_c = 1,
- .has_osd_d = 1,
- .osd_size_off = 0xc,
- .has_osd_alpha = 1,
- .palette_sz = 256,
- .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
- VALID_BPP(15) | VALID_BPP(16) |
- VALID_BPP(18) | VALID_BPP(19) |
- VALID_BPP(24) | VALID_BPP(25) |
- VALID_BPP(32)),
- },
- [3] = {
- .has_osd_c = 1,
- .has_osd_alpha = 1,
- .palette_sz = 256,
- .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
- VALID_BPP(15) | VALID_BPP(16) |
- VALID_BPP(18) | VALID_BPP(19) |
- VALID_BPP(24) | VALID_BPP(25) |
- VALID_BPP(32)),
- },
- [4] = {
- .has_osd_c = 1,
- .has_osd_alpha = 1,
- .palette_sz = 256,
- .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
- VALID_BPP(15) | VALID_BPP(16) |
- VALID_BPP(18) | VALID_BPP(19) |
- VALID_BPP(24) | VALID_BPP(25) |
- VALID_BPP(32)),
- },
-};
-
static struct s3c_fb_driverdata s3c_fb_data_64xx = {
.variant = {
.nr_windows = 5,
@@ -1804,102 +1745,6 @@ static struct s3c_fb_driverdata s3c_fb_data_64xx = {
.win[4] = &s3c_fb_data_64xx_wins[4],
};
-static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
- .variant = {
- .nr_windows = 5,
- .vidtcon = VIDTCON0,
- .wincon = WINCON(0),
- .winmap = WINxMAP(0),
- .keycon = WKEYCON,
- .osd = VIDOSD_BASE,
- .osd_stride = 16,
- .buf_start = VIDW_BUF_START(0),
- .buf_size = VIDW_BUF_SIZE(0),
- .buf_end = VIDW_BUF_END(0),
-
- .palette = {
- [0] = 0x2400,
- [1] = 0x2800,
- [2] = 0x2c00,
- [3] = 0x3000,
- [4] = 0x3400,
- },
-
- .has_shadowcon = 1,
- .has_blendcon = 1,
- .has_clksel = 1,
- .has_fixvclk = 1,
- },
- .win[0] = &s3c_fb_data_s5p_wins[0],
- .win[1] = &s3c_fb_data_s5p_wins[1],
- .win[2] = &s3c_fb_data_s5p_wins[2],
- .win[3] = &s3c_fb_data_s5p_wins[3],
- .win[4] = &s3c_fb_data_s5p_wins[4],
-};
-
-static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
- .variant = {
- .nr_windows = 5,
- .vidtcon = VIDTCON0,
- .wincon = WINCON(0),
- .winmap = WINxMAP(0),
- .keycon = WKEYCON,
- .osd = VIDOSD_BASE,
- .osd_stride = 16,
- .buf_start = VIDW_BUF_START(0),
- .buf_size = VIDW_BUF_SIZE(0),
- .buf_end = VIDW_BUF_END(0),
-
- .palette = {
- [0] = 0x2400,
- [1] = 0x2800,
- [2] = 0x2c00,
- [3] = 0x3000,
- [4] = 0x3400,
- },
-
- .has_shadowcon = 1,
- .has_blendcon = 1,
- .has_fixvclk = 1,
- },
- .win[0] = &s3c_fb_data_s5p_wins[0],
- .win[1] = &s3c_fb_data_s5p_wins[1],
- .win[2] = &s3c_fb_data_s5p_wins[2],
- .win[3] = &s3c_fb_data_s5p_wins[3],
- .win[4] = &s3c_fb_data_s5p_wins[4],
-};
-
-static struct s3c_fb_driverdata s3c_fb_data_exynos5 = {
- .variant = {
- .nr_windows = 5,
- .vidtcon = FIMD_V8_VIDTCON0,
- .wincon = WINCON(0),
- .winmap = WINxMAP(0),
- .keycon = WKEYCON,
- .osd = VIDOSD_BASE,
- .osd_stride = 16,
- .buf_start = VIDW_BUF_START(0),
- .buf_size = VIDW_BUF_SIZE(0),
- .buf_end = VIDW_BUF_END(0),
-
- .palette = {
- [0] = 0x2400,
- [1] = 0x2800,
- [2] = 0x2c00,
- [3] = 0x3000,
- [4] = 0x3400,
- },
- .has_shadowcon = 1,
- .has_blendcon = 1,
- .has_fixvclk = 1,
- },
- .win[0] = &s3c_fb_data_s5p_wins[0],
- .win[1] = &s3c_fb_data_s5p_wins[1],
- .win[2] = &s3c_fb_data_s5p_wins[2],
- .win[3] = &s3c_fb_data_s5p_wins[3],
- .win[4] = &s3c_fb_data_s5p_wins[4],
-};
-
/* S3C2443/S3C2416 style hardware */
static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
.variant = {
@@ -1942,15 +1787,6 @@ static const struct platform_device_id s3c_fb_driver_ids[] = {
.name = "s3c-fb",
.driver_data = (unsigned long)&s3c_fb_data_64xx,
}, {
- .name = "s5pv210-fb",
- .driver_data = (unsigned long)&s3c_fb_data_s5pv210,
- }, {
- .name = "exynos4-fb",
- .driver_data = (unsigned long)&s3c_fb_data_exynos4,
- }, {
- .name = "exynos5-fb",
- .driver_data = (unsigned long)&s3c_fb_data_exynos5,
- }, {
.name = "s3c2443-fb",
.driver_data = (unsigned long)&s3c_fb_data_s3c2443,
},
diff --git a/drivers/video/fbdev/sis/init.h b/drivers/video/fbdev/sis/init.h
index 85d6738b6c64..400b0e5681b2 100644
--- a/drivers/video/fbdev/sis/init.h
+++ b/drivers/video/fbdev/sis/init.h
@@ -1461,81 +1461,5 @@ static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1_H[] =
0x00}}
};
-bool SiSInitPtr(struct SiS_Private *SiS_Pr);
-unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
- int VDisplay, int Depth, bool FSTN,
- unsigned short CustomT, int LCDwith, int LCDheight,
- unsigned int VBFlags2);
-unsigned short SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
- int VDisplay, int Depth, unsigned int VBFlags2);
-unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
- int VDisplay, int Depth, unsigned int VBFlags2);
-
-void SiS_DisplayOn(struct SiS_Private *SiS_Pr);
-void SiS_DisplayOff(struct SiS_Private *SiS_Pr);
-void SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-void SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
-void SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
-unsigned short SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
- unsigned short ModeIdIndex);
-bool SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
-
-bool SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
- unsigned short *ModeIdIndex);
-unsigned short SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
- unsigned short ModeIdIndex);
-unsigned short SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
-unsigned short SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
-unsigned short SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
- unsigned short ModeIdIndex);
-unsigned short SiS_GetOffset(struct SiS_Private *SiS_Pr,unsigned short ModeNo,
- unsigned short ModeIdIndex, unsigned short RRTI);
-#ifdef CONFIG_FB_SIS_300
-void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
- unsigned short *idx2);
-unsigned short SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2);
-unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
-#endif
-void SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
-bool SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
-void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
-void SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
- unsigned short ModeIdIndex);
-void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
- int yres, struct fb_var_screeninfo *var, bool writeres);
-
-/* From init301.c: */
-extern void SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
- unsigned short ModeIdIndex, int chkcrt2mode);
-extern void SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
- unsigned short ModeIdIndex);
-extern void SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
-extern void SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
- unsigned short ModeIdIndex);
-extern void SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
-extern void SiS_DisableBridge(struct SiS_Private *);
-extern bool SiS_SetCRT2Group(struct SiS_Private *, unsigned short);
-extern unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
- unsigned short ModeIdIndex);
-extern void SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
-extern unsigned short SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
- unsigned short ModeIdIndex);
-extern unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
-extern unsigned short SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
- unsigned short ModeIdIndex, unsigned short RRTI);
-extern bool SiS_IsVAMode(struct SiS_Private *);
-extern bool SiS_IsDualEdge(struct SiS_Private *);
-
-#ifdef CONFIG_FB_SIS_300
-extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
-extern void sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg,
- unsigned int val);
-#endif
-#ifdef CONFIG_FB_SIS_315
-extern void sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg,
- unsigned char val);
-extern unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
-#endif
-
#endif
diff --git a/drivers/video/fbdev/sis/init301.c b/drivers/video/fbdev/sis/init301.c
index 02ee752d5000..27a2b72e50e8 100644
--- a/drivers/video/fbdev/sis/init301.c
+++ b/drivers/video/fbdev/sis/init301.c
@@ -82,6 +82,332 @@
#define SiS_I2CDELAY 1000
#define SiS_I2CDELAYSHORT 150
+static const unsigned char SiS_YPbPrTable[3][64] = {
+ {
+ 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
+ 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
+ 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
+ 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
+ 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
+ 0x03,0x0a,0x65,0x9d /*0x8d*/,0x08,0x92,0x8f,0x40,
+ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53 /*0x50*/,
+ 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
+ },
+ {
+ 0x33,0x06,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
+ 0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
+ 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+ 0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
+ 0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
+ 0x51,0x5e,0x60,0x49,0x7d,0x92,0x0f,0x40,
+ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4e,
+ 0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00
+ },
+ {
+#if 0 /* OK, but sticks to left edge */
+ 0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
+ 0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
+ 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+ 0xed,0x50,0x70,0x9f,0x16,0x59,0x21 /*0x2b*/,0x13,
+ 0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
+ 0x4b,0x4b,0x65 /*0x6f*/,0x2f,0x63,0x92,0x0f,0x40,
+ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27,
+ 0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
+#endif
+#if 1 /* Perfect */
+ 0x23,0x2d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
+ 0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
+ 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+ 0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13,
+ 0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
+ 0x4b,0x4b,0x6f,0x2f,0x63,0x92,0x0f,0x40,
+ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x73,
+ 0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
+#endif
+ }
+};
+
+static const unsigned char SiS_TVPhase[] =
+{
+ 0x21,0xED,0xBA,0x08, /* 0x00 SiS_NTSCPhase */
+ 0x2A,0x05,0xE3,0x00, /* 0x01 SiS_PALPhase */
+ 0x21,0xE4,0x2E,0x9B, /* 0x02 SiS_PALMPhase */
+ 0x21,0xF4,0x3E,0xBA, /* 0x03 SiS_PALNPhase */
+ 0x1E,0x8B,0xA2,0xA7,
+ 0x1E,0x83,0x0A,0xE0, /* 0x05 SiS_SpecialPhaseM */
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,
+ 0x21,0xF0,0x7B,0xD6, /* 0x08 SiS_NTSCPhase2 */
+ 0x2A,0x09,0x86,0xE9, /* 0x09 SiS_PALPhase2 */
+ 0x21,0xE6,0xEF,0xA4, /* 0x0a SiS_PALMPhase2 */
+ 0x21,0xF6,0x94,0x46, /* 0x0b SiS_PALNPhase2 */
+ 0x1E,0x8B,0xA2,0xA7,
+ 0x1E,0x83,0x0A,0xE0, /* 0x0d SiS_SpecialPhaseM */
+ 0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,
+ 0x1e,0x8c,0x5c,0x7a, /* 0x10 SiS_SpecialPhase */
+ 0x25,0xd4,0xfd,0x5e /* 0x11 SiS_SpecialPhaseJ */
+};
+
+static const unsigned char SiS_HiTVGroup3_1[] = {
+ 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13,
+ 0xb1, 0x41, 0x62, 0x62, 0xff, 0xf4, 0x45, 0xa6,
+ 0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
+ 0xac, 0xda, 0x60, 0xfe, 0x6a, 0x9a, 0x06, 0x10,
+ 0xd1, 0x04, 0x18, 0x0a, 0xff, 0x80, 0x00, 0x80,
+ 0x3b, 0x77, 0x00, 0xef, 0xe0, 0x10, 0xb0, 0xe0,
+ 0x10, 0x4f, 0x0f, 0x0f, 0x05, 0x0f, 0x08, 0x6e,
+ 0x1a, 0x1f, 0x25, 0x2a, 0x4c, 0xaa, 0x01
+};
+
+static const unsigned char SiS_HiTVGroup3_2[] = {
+ 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a,
+ 0x54, 0x41, 0xe7, 0xe7, 0xff, 0xf4, 0x45, 0xa6,
+ 0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
+ 0xac, 0x6a, 0x60, 0x2b, 0x52, 0xcd, 0x61, 0x10,
+ 0x51, 0x04, 0x18, 0x0a, 0x1f, 0x80, 0x00, 0x80,
+ 0xff, 0xa4, 0x04, 0x2b, 0x94, 0x21, 0x72, 0x94,
+ 0x26, 0x05, 0x01, 0x0f, 0xed, 0x0f, 0x0a, 0x64,
+ 0x18, 0x1d, 0x23, 0x28, 0x4c, 0xaa, 0x01
+};
+
+/* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */
+
+static const unsigned char SiS_Part2CLVX_1[] = {
+ 0x00,0x00,
+ 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
+ 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
+ 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C,
+ 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
+};
+
+static const unsigned char SiS_Part2CLVX_2[] = {
+ 0x00,0x00,
+ 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
+ 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
+ 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C,
+ 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
+};
+
+static const unsigned char SiS_Part2CLVX_3[] = { /* NTSC, 525i, 525p */
+ 0xE0,0x01,
+ 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D,0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D,
+ 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C,0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C,
+ 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E,
+ 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00,0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02,
+ 0x58,0x02,
+ 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D,0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E,
+ 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F,0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F,
+ 0x00,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01,0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03,
+ 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04,0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06,
+ 0x00,0x03,
+ 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00,0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01,
+ 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02,0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03,
+ 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05,0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06,
+ 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07,0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08,
+ 0xFF,0xFF
+};
+
+static const unsigned char SiS_Part2CLVX_4[] = { /* PAL */
+ 0x58,0x02,
+ 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
+ 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
+ 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E,
+ 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04,
+ 0x00,0x03,
+ 0x08,0x12,0x08,0x7E,0x07,0x12,0x09,0x7E,0x06,0x12,0x0A,0x7E,0x05,0x11,0x0B,0x7F,
+ 0x04,0x11,0x0C,0x7F,0x03,0x11,0x0C,0x00,0x03,0x10,0x0D,0x00,0x02,0x0F,0x0E,0x01,
+ 0x01,0x0F,0x0F,0x01,0x01,0x0E,0x0F,0x02,0x00,0x0D,0x10,0x03,0x7F,0x0C,0x11,0x04,
+ 0x7F,0x0C,0x11,0x04,0x7F,0x0B,0x11,0x05,0x7E,0x0A,0x12,0x06,0x7E,0x09,0x12,0x07,
+ 0x40,0x02,
+ 0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
+ 0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
+ 0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F,
+ 0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
+ 0xFF,0xFF
+};
+
+static const unsigned char SiS_Part2CLVX_5[] = { /* 750p */
+ 0x00,0x03,
+ 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
+ 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
+ 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E,
+ 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04,
+ 0xFF,0xFF
+};
+
+static const unsigned char SiS_Part2CLVX_6[] = { /* 1080i */
+ 0x00,0x04,
+ 0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
+ 0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
+ 0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F,
+ 0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
+ 0xFF,0xFF,
+};
+
+#ifdef CONFIG_FB_SIS_315
+/* 661 et al LCD data structure (2.03.00) */
+static const unsigned char SiS_LCDStruct661[] = {
+ /* 1024x768 */
+/* type|CR37| HDE | VDE | HT | VT | hss | hse */
+ 0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
+ 0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x00,0x00,0x00,0x00,0x04,
+ /* | vss | vse |clck| clock |CRT2DataP|CRT2DataP|idx */
+ /* VESA non-VESA noscale */
+ /* 1280x1024 */
+ 0x03,0xC0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70,
+ 0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x08,
+ /* 1400x1050 */
+ 0x09,0x20,0x78,0x05,0x1A,0x04,0x98,0x06,0x2A,0x04,0x18,0x00,0x38,
+ 0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x09,
+ /* 1600x1200 */
+ 0x0B,0xE0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0,
+ 0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x00,0x00,0x00,0x00,0x0A,
+ /* 1280x768 (_2) */
+ 0x0A,0xE0,0x00,0x05,0x00,0x03,0x7C,0x06,0x26,0x03,0x30,0x00,0x70,
+ 0x00,0x03,0x00,0x06,0x00,0x4D,0xC8,0x48,0x00,0x00,0x00,0x00,0x06,
+ /* 1280x720 */
+ 0x0E,0xE0,0x00,0x05,0xD0,0x02,0x80,0x05,0x26,0x03,0x10,0x00,0x20,
+ 0x00,0x01,0x00,0x06,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x05,
+ /* 1280x800 (_2) */
+ 0x0C,0xE0,0x00,0x05,0x20,0x03,0x10,0x06,0x2C,0x03,0x30,0x00,0x70,
+ 0x00,0x04,0x00,0x03,0x00,0x49,0xCE,0x1E,0x00,0x00,0x00,0x00,0x09,
+ /* 1680x1050 */
+ 0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
+ 0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06,
+ /* 1280x800_3 */
+ 0x0C,0xE0,0x00,0x05,0x20,0x03,0xAA,0x05,0x2E,0x03,0x30,0x00,0x50,
+ 0x00,0x04,0x00,0x03,0x00,0x47,0xA9,0x10,0x00,0x00,0x00,0x00,0x07,
+ /* 800x600 */
+ 0x01,0xC0,0x20,0x03,0x58,0x02,0x20,0x04,0x74,0x02,0x2A,0x00,0x80,
+ 0x00,0x06,0x00,0x04,0x00,0x28,0x63,0x4B,0x00,0x00,0x00,0x00,0x00,
+ /* 1280x854 */
+ 0x08,0xE0,0x00,0x05,0x56,0x03,0x80,0x06,0x5d,0x03,0x10,0x00,0x70,
+ 0x00,0x01,0x00,0x03,0x00,0x54,0x75,0x13,0x00,0x00,0x00,0x00,0x08
+};
+#endif
+
+#ifdef CONFIG_FB_SIS_300
+static unsigned char SiS300_TrumpionData[14][80] = {
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+ 0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
+ 0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xBC,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x09,0x04,0x04,0x05,
+ 0x04,0x0C,0x09,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5A,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x27,0x00,0x80,0x02,
+ 0x20,0x03,0x07,0x00,0x5E,0x01,0x0D,0x02,0x60,0x0C,0x30,0x11,0x00,0x00,0x04,0x23,
+ 0x00,0x00,0x03,0x80,0x03,0x28,0x06,0x08,0x40,0x11,0x00,0x11,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0x90,0x01,0xFF,0x0F,0xF4,0x19,0x01,0x00,0x05,0x01,0x00,0x04,0x05,
+ 0x04,0x0C,0x02,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEC,0x57,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
+ 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+ 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xD9,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+ 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x59,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
+ 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+ 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+ 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+ 0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
+ 0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
+ 0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
+ 0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
+ 0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
+ 0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
+ 0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
+ 0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+ /* variant 2 */
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+ 0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
+ 0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+ 0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
+ 0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
+ 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+ 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+ 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
+ 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+ 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+ 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+ 0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
+ 0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
+ 0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
+ 0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
+ 0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
+ 0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
+ { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
+ 0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
+ 0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
+ 0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
+ 0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 }
+};
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+static void SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr);
+static void SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr);
+static void SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr);
+static void SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr);
+#endif /* 315 */
+
+#ifdef CONFIG_FB_SIS_300
+static bool SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
+#endif
+
+static unsigned short SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
+ int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
+ bool checkcr32, unsigned int VBFlags2);
+static unsigned short SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
+ unsigned char *buffer);
+static void SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetStart(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetStop(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetSCLKLow(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax);
+static unsigned short SiS_CheckACK(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_WriteDABDDC(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr);
+static unsigned short SiS_PrepareDDC(struct SiS_Private *SiS_Pr);
+static void SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno);
+static unsigned short SiS_DoProbeDDC(struct SiS_Private *SiS_Pr);
+
+#ifdef CONFIG_FB_SIS_300
+static void SiS_OEM300Setting(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex);
+static void SetOEMLCDData2(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex);
+#endif
+#ifdef CONFIG_FB_SIS_315
+static void SiS_OEM310Setting(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
+static void SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
+ unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
+static void SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short);
+#endif
+
static unsigned short SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
static void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
diff --git a/drivers/video/fbdev/sis/init301.h b/drivers/video/fbdev/sis/init301.h
index 2112d6d7feda..6e5cf14c4ce4 100644
--- a/drivers/video/fbdev/sis/init301.h
+++ b/drivers/video/fbdev/sis/init301.h
@@ -66,287 +66,6 @@
#include "sis.h"
#include <video/sisfb.h>
-static const unsigned char SiS_YPbPrTable[3][64] = {
- {
- 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
- 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
- 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
- 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
- 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
- 0x03,0x0a,0x65,0x9d /*0x8d*/,0x08,0x92,0x8f,0x40,
- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53 /*0x50*/,
- 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
- },
- {
- 0x33,0x06,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
- 0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
- 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
- 0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
- 0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
- 0x51,0x5e,0x60,0x49,0x7d,0x92,0x0f,0x40,
- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4e,
- 0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00
- },
- {
-#if 0 /* OK, but sticks to left edge */
- 0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
- 0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
- 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
- 0xed,0x50,0x70,0x9f,0x16,0x59,0x21 /*0x2b*/,0x13,
- 0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
- 0x4b,0x4b,0x65 /*0x6f*/,0x2f,0x63,0x92,0x0f,0x40,
- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27,
- 0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
-#endif
-#if 1 /* Perfect */
- 0x23,0x2d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
- 0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
- 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
- 0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13,
- 0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
- 0x4b,0x4b,0x6f,0x2f,0x63,0x92,0x0f,0x40,
- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x73,
- 0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
-#endif
- }
-};
-
-static const unsigned char SiS_TVPhase[] =
-{
- 0x21,0xED,0xBA,0x08, /* 0x00 SiS_NTSCPhase */
- 0x2A,0x05,0xE3,0x00, /* 0x01 SiS_PALPhase */
- 0x21,0xE4,0x2E,0x9B, /* 0x02 SiS_PALMPhase */
- 0x21,0xF4,0x3E,0xBA, /* 0x03 SiS_PALNPhase */
- 0x1E,0x8B,0xA2,0xA7,
- 0x1E,0x83,0x0A,0xE0, /* 0x05 SiS_SpecialPhaseM */
- 0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,
- 0x21,0xF0,0x7B,0xD6, /* 0x08 SiS_NTSCPhase2 */
- 0x2A,0x09,0x86,0xE9, /* 0x09 SiS_PALPhase2 */
- 0x21,0xE6,0xEF,0xA4, /* 0x0a SiS_PALMPhase2 */
- 0x21,0xF6,0x94,0x46, /* 0x0b SiS_PALNPhase2 */
- 0x1E,0x8B,0xA2,0xA7,
- 0x1E,0x83,0x0A,0xE0, /* 0x0d SiS_SpecialPhaseM */
- 0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,
- 0x1e,0x8c,0x5c,0x7a, /* 0x10 SiS_SpecialPhase */
- 0x25,0xd4,0xfd,0x5e /* 0x11 SiS_SpecialPhaseJ */
-};
-
-static const unsigned char SiS_HiTVGroup3_1[] = {
- 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13,
- 0xb1, 0x41, 0x62, 0x62, 0xff, 0xf4, 0x45, 0xa6,
- 0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
- 0xac, 0xda, 0x60, 0xfe, 0x6a, 0x9a, 0x06, 0x10,
- 0xd1, 0x04, 0x18, 0x0a, 0xff, 0x80, 0x00, 0x80,
- 0x3b, 0x77, 0x00, 0xef, 0xe0, 0x10, 0xb0, 0xe0,
- 0x10, 0x4f, 0x0f, 0x0f, 0x05, 0x0f, 0x08, 0x6e,
- 0x1a, 0x1f, 0x25, 0x2a, 0x4c, 0xaa, 0x01
-};
-
-static const unsigned char SiS_HiTVGroup3_2[] = {
- 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a,
- 0x54, 0x41, 0xe7, 0xe7, 0xff, 0xf4, 0x45, 0xa6,
- 0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
- 0xac, 0x6a, 0x60, 0x2b, 0x52, 0xcd, 0x61, 0x10,
- 0x51, 0x04, 0x18, 0x0a, 0x1f, 0x80, 0x00, 0x80,
- 0xff, 0xa4, 0x04, 0x2b, 0x94, 0x21, 0x72, 0x94,
- 0x26, 0x05, 0x01, 0x0f, 0xed, 0x0f, 0x0a, 0x64,
- 0x18, 0x1d, 0x23, 0x28, 0x4c, 0xaa, 0x01
-};
-
-/* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */
-
-static const unsigned char SiS_Part2CLVX_1[] = {
- 0x00,0x00,
- 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
- 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
- 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C,
- 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
-};
-
-static const unsigned char SiS_Part2CLVX_2[] = {
- 0x00,0x00,
- 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
- 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
- 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C,
- 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
-};
-
-static const unsigned char SiS_Part2CLVX_3[] = { /* NTSC, 525i, 525p */
- 0xE0,0x01,
- 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D,0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D,
- 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C,0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C,
- 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E,
- 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00,0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02,
- 0x58,0x02,
- 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D,0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E,
- 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F,0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F,
- 0x00,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01,0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03,
- 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04,0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06,
- 0x00,0x03,
- 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00,0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01,
- 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02,0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03,
- 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05,0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06,
- 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07,0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08,
- 0xFF,0xFF
-};
-
-static const unsigned char SiS_Part2CLVX_4[] = { /* PAL */
- 0x58,0x02,
- 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
- 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
- 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E,
- 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04,
- 0x00,0x03,
- 0x08,0x12,0x08,0x7E,0x07,0x12,0x09,0x7E,0x06,0x12,0x0A,0x7E,0x05,0x11,0x0B,0x7F,
- 0x04,0x11,0x0C,0x7F,0x03,0x11,0x0C,0x00,0x03,0x10,0x0D,0x00,0x02,0x0F,0x0E,0x01,
- 0x01,0x0F,0x0F,0x01,0x01,0x0E,0x0F,0x02,0x00,0x0D,0x10,0x03,0x7F,0x0C,0x11,0x04,
- 0x7F,0x0C,0x11,0x04,0x7F,0x0B,0x11,0x05,0x7E,0x0A,0x12,0x06,0x7E,0x09,0x12,0x07,
- 0x40,0x02,
- 0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
- 0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
- 0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F,
- 0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
- 0xFF,0xFF
-};
-
-static const unsigned char SiS_Part2CLVX_5[] = { /* 750p */
- 0x00,0x03,
- 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
- 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
- 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E,
- 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04,
- 0xFF,0xFF
-};
-
-static const unsigned char SiS_Part2CLVX_6[] = { /* 1080i */
- 0x00,0x04,
- 0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
- 0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
- 0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F,
- 0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
- 0xFF,0xFF,
-};
-
-#ifdef CONFIG_FB_SIS_315
-/* 661 et al LCD data structure (2.03.00) */
-static const unsigned char SiS_LCDStruct661[] = {
- /* 1024x768 */
-/* type|CR37| HDE | VDE | HT | VT | hss | hse */
- 0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
- 0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x00,0x00,0x00,0x00,0x04,
- /* | vss | vse |clck| clock |CRT2DataP|CRT2DataP|idx */
- /* VESA non-VESA noscale */
- /* 1280x1024 */
- 0x03,0xC0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70,
- 0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x08,
- /* 1400x1050 */
- 0x09,0x20,0x78,0x05,0x1A,0x04,0x98,0x06,0x2A,0x04,0x18,0x00,0x38,
- 0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x09,
- /* 1600x1200 */
- 0x0B,0xE0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0,
- 0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x00,0x00,0x00,0x00,0x0A,
- /* 1280x768 (_2) */
- 0x0A,0xE0,0x00,0x05,0x00,0x03,0x7C,0x06,0x26,0x03,0x30,0x00,0x70,
- 0x00,0x03,0x00,0x06,0x00,0x4D,0xC8,0x48,0x00,0x00,0x00,0x00,0x06,
- /* 1280x720 */
- 0x0E,0xE0,0x00,0x05,0xD0,0x02,0x80,0x05,0x26,0x03,0x10,0x00,0x20,
- 0x00,0x01,0x00,0x06,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x05,
- /* 1280x800 (_2) */
- 0x0C,0xE0,0x00,0x05,0x20,0x03,0x10,0x06,0x2C,0x03,0x30,0x00,0x70,
- 0x00,0x04,0x00,0x03,0x00,0x49,0xCE,0x1E,0x00,0x00,0x00,0x00,0x09,
- /* 1680x1050 */
- 0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
- 0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06,
- /* 1280x800_3 */
- 0x0C,0xE0,0x00,0x05,0x20,0x03,0xAA,0x05,0x2E,0x03,0x30,0x00,0x50,
- 0x00,0x04,0x00,0x03,0x00,0x47,0xA9,0x10,0x00,0x00,0x00,0x00,0x07,
- /* 800x600 */
- 0x01,0xC0,0x20,0x03,0x58,0x02,0x20,0x04,0x74,0x02,0x2A,0x00,0x80,
- 0x00,0x06,0x00,0x04,0x00,0x28,0x63,0x4B,0x00,0x00,0x00,0x00,0x00,
- /* 1280x854 */
- 0x08,0xE0,0x00,0x05,0x56,0x03,0x80,0x06,0x5d,0x03,0x10,0x00,0x70,
- 0x00,0x01,0x00,0x03,0x00,0x54,0x75,0x13,0x00,0x00,0x00,0x00,0x08
-};
-#endif
-
-#ifdef CONFIG_FB_SIS_300
-static unsigned char SiS300_TrumpionData[14][80] = {
- { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
- 0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
- 0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0xBC,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x09,0x04,0x04,0x05,
- 0x04,0x0C,0x09,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5A,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x27,0x00,0x80,0x02,
- 0x20,0x03,0x07,0x00,0x5E,0x01,0x0D,0x02,0x60,0x0C,0x30,0x11,0x00,0x00,0x04,0x23,
- 0x00,0x00,0x03,0x80,0x03,0x28,0x06,0x08,0x40,0x11,0x00,0x11,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0x90,0x01,0xFF,0x0F,0xF4,0x19,0x01,0x00,0x05,0x01,0x00,0x04,0x05,
- 0x04,0x0C,0x02,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEC,0x57,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
- 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
- 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0xD9,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
- 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x59,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
- 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
- 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
- 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
- 0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
- 0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
- 0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
- 0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
- 0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
- 0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
- 0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
- 0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
- 0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
- 0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
- /* variant 2 */
- { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
- 0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
- 0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
- 0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
- 0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
- 0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
- 0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
- 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
- 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
- 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
- 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
- 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
- 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
- 0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
- 0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
- 0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
- 0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
- 0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
- 0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
- 0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
- { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
- 0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
- 0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
- 0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
- 0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 }
-};
-#endif
-
void SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
void SiS_EnableCRT2(struct SiS_Private *SiS_Pr);
unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
@@ -375,16 +94,11 @@ unsigned short SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempax);
void SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
unsigned char orval,unsigned short andval);
#ifdef CONFIG_FB_SIS_315
-static void SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr);
-static void SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr);
-static void SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr);
-static void SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr);
void SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
void SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
#endif /* 315 */
#ifdef CONFIG_FB_SIS_300
-static bool SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
void SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
#endif
@@ -394,40 +108,6 @@ unsigned short SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, i
unsigned short adaptnum, unsigned short DDCdatatype,
unsigned char *buffer, unsigned int VBFlags2);
-static unsigned short SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
- int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
- bool checkcr32, unsigned int VBFlags2);
-static unsigned short SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
-static unsigned short SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
- unsigned char *buffer);
-static void SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr);
-static unsigned short SiS_SetStart(struct SiS_Private *SiS_Pr);
-static unsigned short SiS_SetStop(struct SiS_Private *SiS_Pr);
-static unsigned short SiS_SetSCLKLow(struct SiS_Private *SiS_Pr);
-static unsigned short SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr);
-static unsigned short SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr);
-static unsigned short SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax);
-static unsigned short SiS_CheckACK(struct SiS_Private *SiS_Pr);
-static unsigned short SiS_WriteDABDDC(struct SiS_Private *SiS_Pr);
-static unsigned short SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr);
-static unsigned short SiS_PrepareDDC(struct SiS_Private *SiS_Pr);
-static void SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno);
-static unsigned short SiS_DoProbeDDC(struct SiS_Private *SiS_Pr);
-
-#ifdef CONFIG_FB_SIS_300
-static void SiS_OEM300Setting(struct SiS_Private *SiS_Pr,
- unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex);
-static void SetOEMLCDData2(struct SiS_Private *SiS_Pr,
- unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex);
-#endif
-#ifdef CONFIG_FB_SIS_315
-static void SiS_OEM310Setting(struct SiS_Private *SiS_Pr,
- unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
-static void SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
- unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
-static void SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short);
-#endif
-
extern void SiS_DisplayOff(struct SiS_Private *SiS_Pr);
extern void SiS_DisplayOn(struct SiS_Private *SiS_Pr);
extern bool SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
diff --git a/drivers/video/fbdev/sis/sis.h b/drivers/video/fbdev/sis/sis.h
index ea1d1c9640bf..d04982b0cd6f 100644
--- a/drivers/video/fbdev/sis/sis.h
+++ b/drivers/video/fbdev/sis/sis.h
@@ -28,6 +28,7 @@
#include "vgatypes.h"
#include "vstruct.h"
+#include "init.h"
#define VER_MAJOR 1
#define VER_MINOR 8
@@ -321,6 +322,85 @@ u8 SiS_GetRegByte(SISIOADDRESS);
u16 SiS_GetRegShort(SISIOADDRESS);
u32 SiS_GetRegLong(SISIOADDRESS);
+/* Chrontel TV, DDC and DPMS functions */
+/* from init.c */
+bool SiSInitPtr(struct SiS_Private *SiS_Pr);
+unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, bool FSTN,
+ unsigned short CustomT, int LCDwith, int LCDheight,
+ unsigned int VBFlags2);
+unsigned short SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+
+void SiS_DisplayOn(struct SiS_Private *SiS_Pr);
+void SiS_DisplayOff(struct SiS_Private *SiS_Pr);
+void SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
+void SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
+void SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
+unsigned short SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+bool SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+
+bool SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+ unsigned short *ModeIdIndex);
+unsigned short SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+unsigned short SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+unsigned short SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+unsigned short SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+unsigned short SiS_GetOffset(struct SiS_Private *SiS_Pr,unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI);
+#ifdef CONFIG_FB_SIS_300
+void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
+ unsigned short *idx2);
+unsigned short SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2);
+unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
+#endif
+void SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+bool SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
+void SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
+ int yres, struct fb_var_screeninfo *var, bool writeres);
+
+/* From init301.c: */
+extern void SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, int chkcrt2mode);
+extern void SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
+extern void SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
+extern void SiS_DisableBridge(struct SiS_Private *);
+extern bool SiS_SetCRT2Group(struct SiS_Private *, unsigned short);
+extern unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern void SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
+extern unsigned short SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex);
+extern unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+extern unsigned short SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+ unsigned short ModeIdIndex, unsigned short RRTI);
+extern bool SiS_IsVAMode(struct SiS_Private *);
+extern bool SiS_IsDualEdge(struct SiS_Private *);
+
+#ifdef CONFIG_FB_SIS_300
+extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+extern void sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg,
+ unsigned int val);
+#endif
+#ifdef CONFIG_FB_SIS_315
+extern void sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg,
+ unsigned char val);
+extern unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
+#endif
+
+
/* MMIO access macros */
#define MMIO_IN8(base, offset) readb((base+offset))
#define MMIO_IN16(base, offset) readw((base+offset))
@@ -583,4 +663,55 @@ struct sis_video_info {
struct sis_video_info *next;
};
+/* from sis_accel.c */
+extern void fbcon_sis_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect);
+extern void fbcon_sis_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area);
+extern int fbcon_sis_sync(struct fb_info *info);
+
+/* Internal 2D accelerator functions */
+extern int sisfb_initaccel(struct sis_video_info *ivideo);
+extern void sisfb_syncaccel(struct sis_video_info *ivideo);
+
+/* Internal general routines */
+#ifdef CONFIG_FB_SIS_300
+unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+void sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val);
+unsigned int sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+#endif
+#ifdef CONFIG_FB_SIS_315
+void sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val);
+unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
+#endif
+
+/* SiS-specific exported functions */
+void sis_malloc(struct sis_memreq *req);
+void sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req);
+void sis_free(u32 base);
+void sis_free_new(struct pci_dev *pdev, u32 base);
+
+/* Routines from init.c/init301.c */
+extern unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, bool FSTN, unsigned short CustomT,
+ int LCDwith, int LCDheight, unsigned int VBFlags2);
+extern unsigned short SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+extern unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
+ int VDisplay, int Depth, unsigned int VBFlags2);
+extern void SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
+extern bool SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+extern void SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
+extern void SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
+
+extern bool SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+
+extern bool sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ int *htotal, int *vtotal, unsigned char rateindex);
+extern int sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
+ unsigned char modeno, unsigned char rateindex);
+extern int sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+ unsigned char rateindex, struct fb_var_screeninfo *var);
+
+
#endif
diff --git a/drivers/video/fbdev/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c
index ecdd054d8951..20aff9005978 100644
--- a/drivers/video/fbdev/sis/sis_main.c
+++ b/drivers/video/fbdev/sis/sis_main.c
@@ -56,15 +56,66 @@
#include "sis.h"
#include "sis_main.h"
+#include "init301.h"
#if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
#warning sisfb will not work!
#endif
+/* ---------------------- Prototypes ------------------------- */
+
+/* Interface used by the world */
+#ifndef MODULE
+static int sisfb_setup(char *options);
+#endif
+
+/* Interface to the low level console driver */
+static int sisfb_init(void);
+
+/* fbdev routines */
+static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+
+static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg);
+static int sisfb_set_par(struct fb_info *info);
+static int sisfb_blank(int blank,
+ struct fb_info *info);
+
static void sisfb_handle_command(struct sis_video_info *ivideo,
struct sisfb_cmd *sisfb_command);
+static void sisfb_search_mode(char *name, bool quiet);
+static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
+static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
+ int index);
+static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *fb_info);
+static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+ struct fb_info *info);
+static void sisfb_pre_setmode(struct sis_video_info *ivideo);
+static void sisfb_post_setmode(struct sis_video_info *ivideo);
+static bool sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
+static bool sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
+static bool sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
+static bool sisfb_bridgeisslave(struct sis_video_info *ivideo);
+static void sisfb_detect_VB_connect(struct sis_video_info *ivideo);
+static void sisfb_get_VB_type(struct sis_video_info *ivideo);
+static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
+static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
+
+/* Internal heap routines */
+static int sisfb_heap_init(struct sis_video_info *ivideo);
+static struct SIS_OH * sisfb_poh_new_node(struct SIS_HEAP *memheap);
+static struct SIS_OH * sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
+static void sisfb_delete_node(struct SIS_OH *poh);
+static void sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
+static struct SIS_OH * sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
+static void sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
+
+
/* ------------------ Internal helper routines ----------------- */
static void __init
diff --git a/drivers/video/fbdev/sis/sis_main.h b/drivers/video/fbdev/sis/sis_main.h
index 32e23c209430..d8ba07061f1e 100644
--- a/drivers/video/fbdev/sis/sis_main.h
+++ b/drivers/video/fbdev/sis/sis_main.h
@@ -661,121 +661,4 @@ static struct _customttable {
}
};
-/* ---------------------- Prototypes ------------------------- */
-
-/* Interface used by the world */
-#ifndef MODULE
-static int sisfb_setup(char *options);
#endif
-
-/* Interface to the low level console driver */
-static int sisfb_init(void);
-
-/* fbdev routines */
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info);
-
-static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
- unsigned long arg);
-static int sisfb_set_par(struct fb_info *info);
-static int sisfb_blank(int blank,
- struct fb_info *info);
-extern void fbcon_sis_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect);
-extern void fbcon_sis_copyarea(struct fb_info *info,
- const struct fb_copyarea *area);
-extern int fbcon_sis_sync(struct fb_info *info);
-
-/* Internal 2D accelerator functions */
-extern int sisfb_initaccel(struct sis_video_info *ivideo);
-extern void sisfb_syncaccel(struct sis_video_info *ivideo);
-
-/* Internal general routines */
-static void sisfb_search_mode(char *name, bool quiet);
-static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
-static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
- int index);
-static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *fb_info);
-static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
- struct fb_info *info);
-static void sisfb_pre_setmode(struct sis_video_info *ivideo);
-static void sisfb_post_setmode(struct sis_video_info *ivideo);
-static bool sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
-static bool sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
-static bool sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
-static bool sisfb_bridgeisslave(struct sis_video_info *ivideo);
-static void sisfb_detect_VB_connect(struct sis_video_info *ivideo);
-static void sisfb_get_VB_type(struct sis_video_info *ivideo);
-static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
-static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
-#ifdef CONFIG_FB_SIS_300
-unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
-void sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val);
-unsigned int sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
-#endif
-#ifdef CONFIG_FB_SIS_315
-void sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val);
-unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
-#endif
-
-/* SiS-specific exported functions */
-void sis_malloc(struct sis_memreq *req);
-void sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req);
-void sis_free(u32 base);
-void sis_free_new(struct pci_dev *pdev, u32 base);
-
-/* Internal heap routines */
-static int sisfb_heap_init(struct sis_video_info *ivideo);
-static struct SIS_OH * sisfb_poh_new_node(struct SIS_HEAP *memheap);
-static struct SIS_OH * sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
-static void sisfb_delete_node(struct SIS_OH *poh);
-static void sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
-static struct SIS_OH * sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
-static void sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
-
-/* Routines from init.c/init301.c */
-extern unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
- int VDisplay, int Depth, bool FSTN, unsigned short CustomT,
- int LCDwith, int LCDheight, unsigned int VBFlags2);
-extern unsigned short SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
- int VDisplay, int Depth, unsigned int VBFlags2);
-extern unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
- int VDisplay, int Depth, unsigned int VBFlags2);
-extern void SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-extern bool SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
-extern void SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
-extern void SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
-
-extern bool SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
-
-extern bool sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
- int *htotal, int *vtotal, unsigned char rateindex);
-extern int sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
- unsigned char modeno, unsigned char rateindex);
-extern int sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
- unsigned char rateindex, struct fb_var_screeninfo *var);
-
-/* Chrontel TV, DDC and DPMS functions */
-extern unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg);
-extern void SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
-extern unsigned short SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg);
-extern void SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
-extern void SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
- unsigned char myor, unsigned char myand);
-extern void SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime);
-extern void SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
-extern unsigned short SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
- unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
- unsigned int VBFlags2);
-extern unsigned short SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr);
-#ifdef CONFIG_FB_SIS_315
-extern void SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
-extern void SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
-#endif
-extern void SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
-extern void SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
-#endif
-
-
diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c
index 8db7085e5d1a..22b606af0a87 100644
--- a/drivers/video/fbdev/smscufx.c
+++ b/drivers/video/fbdev/smscufx.c
@@ -1293,7 +1293,6 @@ static struct fb_ops ufx_ops = {
* Assumes no active clients have framebuffer open */
static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info)
{
- int retval = -ENOMEM;
int old_len = info->fix.smem_len;
int new_len;
unsigned char *old_fb = info->screen_base;
@@ -1308,10 +1307,8 @@ static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info)
* Alloc system memory for virtual framebuffer
*/
new_fb = vmalloc(new_len);
- if (!new_fb) {
- pr_err("Virtual framebuffer alloc failed");
- goto error;
- }
+ if (!new_fb)
+ return -ENOMEM;
if (info->screen_base) {
memcpy(new_fb, old_fb, old_len);
@@ -1323,11 +1320,7 @@ static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info)
info->fix.smem_start = (unsigned long) new_fb;
info->flags = smscufx_info_flags;
}
-
- retval = 0;
-
-error:
- return retval;
+ return 0;
}
/* sets up I2C Controller for 100 Kbps, std. speed, 7-bit addr, master,
@@ -1620,8 +1613,8 @@ static int ufx_usb_probe(struct usb_interface *interface,
{
struct usb_device *usbdev;
struct ufx_data *dev;
- struct fb_info *info = NULL;
- int retval = -ENOMEM;
+ struct fb_info *info;
+ int retval;
u32 id_rev, fpga_rev;
/* usb initialization */
@@ -1631,7 +1624,7 @@ static int ufx_usb_probe(struct usb_interface *interface,
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
dev_err(&usbdev->dev, "ufx_usb_probe: failed alloc of dev struct\n");
- goto error;
+ return -ENOMEM;
}
/* we need to wait for both usb and fbdev to spin down on disconnect */
@@ -1652,9 +1645,8 @@ static int ufx_usb_probe(struct usb_interface *interface,
dev_dbg(dev->gdev, "fb_defio enable=%d\n", fb_defio);
if (!ufx_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
- retval = -ENOMEM;
dev_err(dev->gdev, "ufx_alloc_urb_list failed\n");
- goto error;
+ goto e_nomem;
}
/* We don't register a new USB class. Our client interface is fbdev */
@@ -1662,9 +1654,8 @@ static int ufx_usb_probe(struct usb_interface *interface,
/* allocates framebuffer driver structure, not framebuffer memory */
info = framebuffer_alloc(0, &usbdev->dev);
if (!info) {
- retval = -ENOMEM;
dev_err(dev->gdev, "framebuffer_alloc failed\n");
- goto error;
+ goto e_nomem;
}
dev->info = info;
@@ -1675,7 +1666,7 @@ static int ufx_usb_probe(struct usb_interface *interface,
retval = fb_alloc_cmap(&info->cmap, 256, 0);
if (retval < 0) {
dev_err(dev->gdev, "fb_alloc_cmap failed %x\n", retval);
- goto error;
+ goto destroy_modedb;
}
INIT_DELAYED_WORK(&dev->free_framebuffer_work,
@@ -1736,26 +1727,20 @@ static int ufx_usb_probe(struct usb_interface *interface,
return 0;
error:
- if (dev) {
- if (info) {
- if (info->cmap.len != 0)
- fb_dealloc_cmap(&info->cmap);
- if (info->monspecs.modedb)
- fb_destroy_modedb(info->monspecs.modedb);
- vfree(info->screen_base);
-
- fb_destroy_modelist(&info->modelist);
-
- framebuffer_release(info);
- }
-
- kref_put(&dev->kref, ufx_free); /* ref for framebuffer */
- kref_put(&dev->kref, ufx_free); /* last ref from kref_init */
-
- /* dev has been deallocated. Do not dereference */
- }
-
+ fb_dealloc_cmap(&info->cmap);
+destroy_modedb:
+ fb_destroy_modedb(info->monspecs.modedb);
+ vfree(info->screen_base);
+ fb_destroy_modelist(&info->modelist);
+ framebuffer_release(info);
+put_ref:
+ kref_put(&dev->kref, ufx_free); /* ref for framebuffer */
+ kref_put(&dev->kref, ufx_free); /* last ref from kref_init */
return retval;
+
+e_nomem:
+ retval = -ENOMEM;
+ goto put_ref;
}
static void ufx_usb_disconnect(struct usb_interface *interface)
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index f599520374dd..6439231f2db2 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -628,7 +628,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
goto fb_alloc_error;
}
- ssd1307fb_defio = devm_kzalloc(&client->dev, sizeof(struct fb_deferred_io), GFP_KERNEL);
+ ssd1307fb_defio = devm_kzalloc(&client->dev, sizeof(*ssd1307fb_defio),
+ GFP_KERNEL);
if (!ssd1307fb_defio) {
dev_err(&client->dev, "Couldn't allocate deferred io.\n");
ret = -ENOMEM;
diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c
index 3c2e4cabc08f..045e8afe398b 100644
--- a/drivers/video/fbdev/stifb.c
+++ b/drivers/video/fbdev/stifb.c
@@ -1126,10 +1126,8 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
int bpp, xres, yres;
fb = kzalloc(sizeof(*fb), GFP_ATOMIC);
- if (!fb) {
- printk(KERN_ERR "stifb: Could not allocate stifb structure\n");
- return -ENODEV;
- }
+ if (!fb)
+ return -ENOMEM;
info = &fb->info;
diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
index 452a4207ac1b..f365d4862015 100644
--- a/drivers/video/fbdev/udlfb.c
+++ b/drivers/video/fbdev/udlfb.c
@@ -428,7 +428,6 @@ static void dlfb_compress_hline(
const uint16_t *pixel = *pixel_start_ptr;
uint32_t dev_addr = *device_address_ptr;
uint8_t *cmd = *command_buffer_ptr;
- const int bpp = 2;
while ((pixel_end > pixel) &&
(cmd_buffer_end - MIN_RLX_CMD_BYTES > cmd)) {
@@ -441,9 +440,9 @@ static void dlfb_compress_hline(
*cmd++ = 0xAF;
*cmd++ = 0x6B;
- *cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF);
- *cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF);
- *cmd++ = (uint8_t) ((dev_addr) & 0xFF);
+ *cmd++ = dev_addr >> 16;
+ *cmd++ = dev_addr >> 8;
+ *cmd++ = dev_addr;
cmd_pixels_count_byte = cmd++; /* we'll know this later */
cmd_pixel_start = pixel;
@@ -453,15 +452,15 @@ static void dlfb_compress_hline(
cmd_pixel_end = pixel + min(MAX_CMD_PIXELS + 1,
min((int)(pixel_end - pixel),
- (int)(cmd_buffer_end - cmd) / bpp));
+ (int)(cmd_buffer_end - cmd) / BPP));
- prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp);
+ prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * BPP);
while (pixel < cmd_pixel_end) {
const uint16_t * const repeating_pixel = pixel;
- *(uint16_t *)cmd = cpu_to_be16p(pixel);
- cmd += 2;
+ *cmd++ = *pixel >> 8;
+ *cmd++ = *pixel;
pixel++;
if (unlikely((pixel < cmd_pixel_end) &&
@@ -490,7 +489,7 @@ static void dlfb_compress_hline(
}
*cmd_pixels_count_byte = (pixel - cmd_pixel_start) & 0xFF;
- dev_addr += (pixel - cmd_pixel_start) * bpp;
+ dev_addr += (pixel - cmd_pixel_start) * BPP;
}
if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
@@ -1136,7 +1135,6 @@ static struct fb_ops dlfb_ops = {
*/
static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info)
{
- int retval = -ENOMEM;
int old_len = info->fix.smem_len;
int new_len;
unsigned char *old_fb = info->screen_base;
@@ -1152,7 +1150,7 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info
new_fb = vmalloc(new_len);
if (!new_fb) {
dev_err(info->dev, "Virtual framebuffer alloc failed\n");
- goto error;
+ return -ENOMEM;
}
if (info->screen_base) {
@@ -1181,11 +1179,7 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info
dlfb->backing_buffer = new_back;
}
}
-
- retval = 0;
-
-error:
- return retval;
+ return 0;
}
/*
@@ -1531,15 +1525,16 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dlfb,
u8 length;
u16 key;
- key = le16_to_cpu(*((u16 *) desc));
- desc += sizeof(u16);
- length = *desc;
- desc++;
+ key = *desc++;
+ key |= (u16)*desc++ << 8;
+ length = *desc++;
switch (key) {
case 0x0200: { /* max_area */
- u32 max_area;
- max_area = le32_to_cpu(*((u32 *)desc));
+ u32 max_area = *desc++;
+ max_area |= (u32)*desc++ << 8;
+ max_area |= (u32)*desc++ << 16;
+ max_area |= (u32)*desc++ << 24;
dev_warn(&intf->dev,
"DL chip limited to %d pixel modes\n",
max_area);
diff --git a/drivers/video/fbdev/vermilion/vermilion.c b/drivers/video/fbdev/vermilion/vermilion.c
index 6f8d444eb0e3..5172fa581147 100644
--- a/drivers/video/fbdev/vermilion/vermilion.c
+++ b/drivers/video/fbdev/vermilion/vermilion.c
@@ -651,7 +651,7 @@ static int vmlfb_check_var_locked(struct fb_var_screeninfo *var,
}
pitch = ALIGN((var->xres * var->bits_per_pixel) >> 3, 0x40);
- mem = pitch * var->yres_virtual;
+ mem = (u64)pitch * var->yres_virtual;
if (mem > vinfo->vram_contig_size) {
return -ENOMEM;
}
diff --git a/drivers/video/fbdev/via/via_aux_sii164.c b/drivers/video/fbdev/via/via_aux_sii164.c
index ca1b35f033b1..c27f62c2c75a 100644
--- a/drivers/video/fbdev/via/via_aux_sii164.c
+++ b/drivers/video/fbdev/via/via_aux_sii164.c
@@ -36,7 +36,7 @@ static void probe(struct via_aux_bus *bus, u8 addr)
.name = name};
/* check vendor id and device id */
const u8 id[] = {0x01, 0x00, 0x06, 0x00}, len = ARRAY_SIZE(id);
- u8 tmp[len];
+ u8 tmp[ARRAY_SIZE(id)];
if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
return;
diff --git a/drivers/video/fbdev/via/via_aux_vt1631.c b/drivers/video/fbdev/via/via_aux_vt1631.c
index 06e742f1f723..32978a0ccfd7 100644
--- a/drivers/video/fbdev/via/via_aux_vt1631.c
+++ b/drivers/video/fbdev/via/via_aux_vt1631.c
@@ -36,7 +36,7 @@ void via_aux_vt1631_probe(struct via_aux_bus *bus)
.name = name};
/* check vendor id and device id */
const u8 id[] = {0x06, 0x11, 0x91, 0x31}, len = ARRAY_SIZE(id);
- u8 tmp[len];
+ u8 tmp[ARRAY_SIZE(id)];
if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
return;
diff --git a/drivers/video/fbdev/via/via_aux_vt1632.c b/drivers/video/fbdev/via/via_aux_vt1632.c
index d24f4cd97401..cec8cc43d524 100644
--- a/drivers/video/fbdev/via/via_aux_vt1632.c
+++ b/drivers/video/fbdev/via/via_aux_vt1632.c
@@ -36,7 +36,7 @@ static void probe(struct via_aux_bus *bus, u8 addr)
.name = name};
/* check vendor id and device id */
const u8 id[] = {0x06, 0x11, 0x92, 0x31}, len = ARRAY_SIZE(id);
- u8 tmp[len];
+ u8 tmp[ARRAY_SIZE(id)];
if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
return;
diff --git a/drivers/video/fbdev/via/via_aux_vt1636.c b/drivers/video/fbdev/via/via_aux_vt1636.c
index 9e015c101d4d..2b10bc21ab79 100644
--- a/drivers/video/fbdev/via/via_aux_vt1636.c
+++ b/drivers/video/fbdev/via/via_aux_vt1636.c
@@ -36,7 +36,7 @@ void via_aux_vt1636_probe(struct via_aux_bus *bus)
.name = name};
/* check vendor id and device id */
const u8 id[] = {0x06, 0x11, 0x45, 0x33}, len = ARRAY_SIZE(id);
- u8 tmp[len];
+ u8 tmp[ARRAY_SIZE(id)];
if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
return;
diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
index 8ce0a99bf17c..83b8963c9657 100644
--- a/drivers/video/of_display_timing.c
+++ b/drivers/video/of_display_timing.c
@@ -244,23 +244,3 @@ dispfail:
return NULL;
}
EXPORT_SYMBOL_GPL(of_get_display_timings);
-
-/**
- * of_display_timings_exist - check if a display-timings node is provided
- * @np: device_node with the timing
- **/
-int of_display_timings_exist(const struct device_node *np)
-{
- struct device_node *timings_np;
-
- if (!np)
- return -EINVAL;
-
- timings_np = of_parse_phandle(np, "display-timings", 0);
- if (!timings_np)
- return -EINVAL;
-
- of_node_put(timings_np);
- return 1;
-}
-EXPORT_SYMBOL_GPL(of_display_timings_exist);
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index dfe5684000be..6b237e3f4983 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -272,6 +272,12 @@ static unsigned int update_balloon_stats(struct virtio_balloon *vb)
pages_to_bytes(events[PSWPOUT]));
update_stat(vb, idx++, VIRTIO_BALLOON_S_MAJFLT, events[PGMAJFAULT]);
update_stat(vb, idx++, VIRTIO_BALLOON_S_MINFLT, events[PGFAULT]);
+#ifdef CONFIG_HUGETLB_PAGE
+ update_stat(vb, idx++, VIRTIO_BALLOON_S_HTLB_PGALLOC,
+ events[HTLB_BUDDY_PGALLOC]);
+ update_stat(vb, idx++, VIRTIO_BALLOON_S_HTLB_PGFAIL,
+ events[HTLB_BUDDY_PGALLOC_FAIL]);
+#endif
#endif
update_stat(vb, idx++, VIRTIO_BALLOON_S_MEMFREE,
pages_to_bytes(i.freeram));
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 23e391d3ec01..b29f4e40851f 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -53,6 +53,8 @@ static unsigned long *acpi_ids_done;
static unsigned long *acpi_id_present;
/* And if there is an _CST definition (or a PBLK) for the ACPI IDs */
static unsigned long *acpi_id_cst_present;
+/* Which ACPI P-State dependencies for a enumerated processor */
+static struct acpi_psd_package *acpi_psd;
static int push_cxx_to_hypervisor(struct acpi_processor *_pr)
{
@@ -362,9 +364,9 @@ read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
}
/* There are more ACPI Processor objects than in x2APIC or MADT.
* This can happen with incorrect ACPI SSDT declerations. */
- if (acpi_id > nr_acpi_bits) {
- pr_debug("We only have %u, trying to set %u\n",
- nr_acpi_bits, acpi_id);
+ if (acpi_id >= nr_acpi_bits) {
+ pr_debug("max acpi id %u, trying to set %u\n",
+ nr_acpi_bits - 1, acpi_id);
return AE_OK;
}
/* OK, There is a ACPI Processor object */
@@ -372,6 +374,13 @@ read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
pr_debug("ACPI CPU%u w/ PBLK:0x%lx\n", acpi_id, (unsigned long)pblk);
+ /* It has P-state dependencies */
+ if (!acpi_processor_get_psd(handle, &acpi_psd[acpi_id])) {
+ pr_debug("ACPI CPU%u w/ PST:coord_type = %llu domain = %llu\n",
+ acpi_id, acpi_psd[acpi_id].coord_type,
+ acpi_psd[acpi_id].domain);
+ }
+
status = acpi_evaluate_object(handle, "_CST", NULL, &buffer);
if (ACPI_FAILURE(status)) {
if (!pblk)
@@ -405,6 +414,14 @@ static int check_acpi_ids(struct acpi_processor *pr_backup)
return -ENOMEM;
}
+ acpi_psd = kcalloc(nr_acpi_bits, sizeof(struct acpi_psd_package),
+ GFP_KERNEL);
+ if (!acpi_psd) {
+ kfree(acpi_id_present);
+ kfree(acpi_id_cst_present);
+ return -ENOMEM;
+ }
+
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX,
read_acpi_id, NULL, NULL, NULL);
@@ -417,6 +434,12 @@ upload:
pr_backup->acpi_id = i;
/* Mask out C-states if there are no _CST or PBLK */
pr_backup->flags.power = test_bit(i, acpi_id_cst_present);
+ /* num_entries is non-zero if we evaluated _PSD */
+ if (acpi_psd[i].num_entries) {
+ memcpy(&pr_backup->performance->domain_info,
+ &acpi_psd[i],
+ sizeof(struct acpi_psd_package));
+ }
(void)upload_pm_data(pr_backup);
}
}
@@ -566,6 +589,7 @@ static void __exit xen_acpi_processor_exit(void)
kfree(acpi_ids_done);
kfree(acpi_id_present);
kfree(acpi_id_cst_present);
+ kfree(acpi_psd);
for_each_possible_cpu(i)
acpi_processor_unregister_performance(i);
diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c
index a493e99bed21..0d6d9264d6a9 100644
--- a/drivers/xen/xenbus/xenbus_dev_frontend.c
+++ b/drivers/xen/xenbus/xenbus_dev_frontend.c
@@ -365,7 +365,7 @@ void xenbus_dev_queue_reply(struct xb_req_data *req)
if (WARN_ON(rc))
goto out;
}
- } else if (req->msg.type == XS_TRANSACTION_END) {
+ } else if (req->type == XS_TRANSACTION_END) {
trans = xenbus_get_transaction(u, req->msg.tx_id);
if (WARN_ON(!trans))
goto out;
@@ -429,6 +429,10 @@ static int xenbus_write_transaction(unsigned msg_type,
{
int rc;
struct xenbus_transaction_holder *trans = NULL;
+ struct {
+ struct xsd_sockmsg hdr;
+ char body[];
+ } *msg = (void *)u->u.buffer;
if (msg_type == XS_TRANSACTION_START) {
trans = kzalloc(sizeof(*trans), GFP_KERNEL);
@@ -437,11 +441,15 @@ static int xenbus_write_transaction(unsigned msg_type,
goto out;
}
list_add(&trans->list, &u->transactions);
- } else if (u->u.msg.tx_id != 0 &&
- !xenbus_get_transaction(u, u->u.msg.tx_id))
+ } else if (msg->hdr.tx_id != 0 &&
+ !xenbus_get_transaction(u, msg->hdr.tx_id))
return xenbus_command_reply(u, XS_ERROR, "ENOENT");
+ else if (msg_type == XS_TRANSACTION_END &&
+ !(msg->hdr.len == 2 &&
+ (!strcmp(msg->body, "T") || !strcmp(msg->body, "F"))))
+ return xenbus_command_reply(u, XS_ERROR, "EINVAL");
- rc = xenbus_dev_request_and_reply(&u->u.msg, u);
+ rc = xenbus_dev_request_and_reply(&msg->hdr, u);
if (rc && trans) {
list_del(&trans->list);
kfree(trans);
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index 3f3b29398ab8..49a3874ae6bb 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -140,7 +140,9 @@ void xs_request_exit(struct xb_req_data *req)
spin_lock(&xs_state_lock);
xs_state_users--;
if ((req->type == XS_TRANSACTION_START && req->msg.type == XS_ERROR) ||
- req->type == XS_TRANSACTION_END)
+ (req->type == XS_TRANSACTION_END &&
+ !WARN_ON_ONCE(req->msg.type == XS_ERROR &&
+ !strcmp(req->body, "ENOENT"))))
xs_state_users--;
spin_unlock(&xs_state_lock);