summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AndroidKernel.mk8
-rw-r--r--Documentation/devicetree/bindings/arm/msm/msm_thermal.txt6
-rw-r--r--Documentation/devicetree/bindings/cnss/icnss.txt10
-rw-r--r--Documentation/devicetree/bindings/iommu/iommu-debug.txt27
-rw-r--r--Documentation/devicetree/bindings/media/video/msm-jpegdma.txt3
-rw-r--r--Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt3
-rw-r--r--Documentation/kernel-parameters.txt9
-rw-r--r--arch/arm/boot/dts/qcom/msm-arm-smmu-8996.dtsi13
-rw-r--r--arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi11
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-cdp.dtsi25
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-mtp.dtsi25
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi217
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi5
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi5
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi43
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi60
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi37
-rw-r--r--arch/arm64/configs/msm_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig5
-rw-r--r--arch/arm64/configs/msmcortex_defconfig11
-rw-r--r--drivers/clk/msm/clock-gcc-cobalt.c5
-rw-r--r--drivers/edac/cortex_arm64_edac.c10
-rw-r--r--drivers/gpu/msm/Makefile3
-rw-r--r--drivers/gpu/msm/a3xx_reg.h312
-rw-r--r--drivers/gpu/msm/a4xx_reg.h82
-rw-r--r--drivers/gpu/msm/a5xx_reg.h20
-rw-r--r--drivers/gpu/msm/adreno.c22
-rw-r--r--drivers/gpu/msm/adreno.h27
-rw-r--r--drivers/gpu/msm/adreno_a3xx.h30
-rw-r--r--drivers/gpu/msm/adreno_a4xx.h35
-rw-r--r--drivers/gpu/msm/adreno_a5xx.c3
-rw-r--r--drivers/gpu/msm/adreno_a5xx.h59
-rw-r--r--drivers/gpu/msm/adreno_a5xx_snapshot.c39
-rw-r--r--drivers/gpu/msm/adreno_coresight.c5
-rw-r--r--drivers/gpu/msm/adreno_dispatch.c7
-rw-r--r--drivers/gpu/msm/adreno_drawctxt.c2
-rw-r--r--drivers/gpu/msm/adreno_drawctxt.h3
-rw-r--r--drivers/gpu/msm/adreno_perfcounter.c4
-rw-r--r--drivers/gpu/msm/adreno_pm4types.h81
-rw-r--r--drivers/gpu/msm/adreno_ringbuffer.h11
-rw-r--r--drivers/gpu/msm/adreno_snapshot.c53
-rw-r--r--drivers/gpu/msm/adreno_trace.h189
-rw-r--r--drivers/gpu/msm/kgsl.c70
-rw-r--r--drivers/gpu/msm/kgsl_cffdump.c4
-rw-r--r--drivers/gpu/msm/kgsl_compat.h12
-rw-r--r--drivers/gpu/msm/kgsl_device.h14
-rw-r--r--drivers/gpu/msm/kgsl_iommu.c182
-rw-r--r--drivers/gpu/msm/kgsl_iommu.h14
-rw-r--r--drivers/gpu/msm/kgsl_log.h32
-rw-r--r--drivers/gpu/msm/kgsl_mmu.c25
-rw-r--r--drivers/gpu/msm/kgsl_mmu.h15
-rw-r--r--drivers/gpu/msm/kgsl_pool.c341
-rw-r--r--drivers/gpu/msm/kgsl_pool.h43
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c11
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.h2
-rw-r--r--drivers/gpu/msm/kgsl_pwrscale.c3
-rw-r--r--drivers/gpu/msm/kgsl_sharedmem.c187
-rw-r--r--drivers/iommu/iommu-debug.c29
-rw-r--r--drivers/irqchip/Makefile1
-rw-r--r--drivers/irqchip/irq-msm.c58
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c25
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c19
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.h4
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_hwreg.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c22
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c6
-rw-r--r--drivers/media/platform/msm/vidc/hfi_packetization.c8
-rw-r--r--drivers/media/platform/msm/vidc/msm_venc.c23
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc.c1
-rw-r--r--drivers/media/platform/msm/vidc/vidc_hfi_api.h1
-rw-r--r--drivers/media/platform/msm/vidc/vidc_hfi_helper.h4
-rw-r--r--drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c10
-rw-r--r--drivers/platform/msm/ipa/ipa_clients/odu_bridge.c83
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa.c5
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_dp.c14
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_i.h2
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c12
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_rt.c6
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_uc.c11
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_utils.c5
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_dma.c52
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c78
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h39
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_i.h24
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c118
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c24
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h34
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c225
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h35
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h71
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c48
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c16
-rw-r--r--drivers/platform/msm/msm_11ad/msm_11ad.c8
-rw-r--r--drivers/regulator/cpr3-mmss-regulator.c13
-rw-r--r--drivers/soc/qcom/Kconfig31
-rw-r--r--drivers/soc/qcom/Makefile3
-rw-r--r--drivers/soc/qcom/icnss.c156
-rw-r--r--drivers/soc/qcom/rpm_log.c549
-rw-r--r--drivers/soc/qcom/rpm_log.h35
-rw-r--r--drivers/soc/qcom/rpm_master_stat.c473
-rw-r--r--drivers/soc/qcom/rpm_rbcpr_stats_v2.c421
-rw-r--r--drivers/soc/qcom/rpm_stats.c570
-rw-r--r--drivers/soc/qcom/rpm_stats.h42
-rw-r--r--drivers/spmi/spmi-pmic-arb.c17
-rw-r--r--drivers/thermal/msm_thermal.c235
-rw-r--r--drivers/usb/gadget/function/f_diag.c25
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.c18
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c978
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.h10
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_util.c24
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_util.h14
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c9
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.c26
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h1
-rw-r--r--include/dt-bindings/clock/msm-clocks-hwio-cobalt.h3
-rw-r--r--include/linux/sched.h4
-rw-r--r--include/linux/workqueue.h6
-rw-r--r--include/uapi/media/msm_jpeg_dma.h1
-rw-r--r--kernel/sched/clock.c2
-rw-r--r--kernel/time/tick-sched.c6
-rw-r--r--kernel/watchdog.c18
-rw-r--r--kernel/workqueue.c174
-rw-r--r--lib/Kconfig.debug31
-rw-r--r--lib/Makefile3
-rw-r--r--mm/memtest.c4
-rw-r--r--mm/page_owner.c6
-rw-r--r--net/ipc_router/ipc_router_core.c30
-rw-r--r--security/pfe/pfk_ice.c20
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c6
134 files changed, 5437 insertions, 2146 deletions
diff --git a/AndroidKernel.mk b/AndroidKernel.mk
index 4914401f3fda..b1b28993e325 100644
--- a/AndroidKernel.mk
+++ b/AndroidKernel.mk
@@ -113,9 +113,11 @@ fi
endef
ifneq ($(KERNEL_LEGACY_DIR),true)
-$(KERNEL_USR): $(TARGET_PREBUILT_INT_KERNEL)
+$(KERNEL_USR): $(KERNEL_HEADERS_INSTALL)
rm -rf $(KERNEL_SYMLINK)
ln -s kernel/$(TARGET_KERNEL) $(KERNEL_SYMLINK)
+
+$(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_USR)
endif
$(KERNEL_OUT):
@@ -139,12 +141,12 @@ $(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_OUT) $(KERNEL_HEADERS_INSTALL)
$(KERNEL_HEADERS_INSTALL): $(KERNEL_OUT)
$(hide) if [ ! -z "$(KERNEL_HEADER_DEFCONFIG)" ]; then \
- $(hide) rm -f $(BUILD_ROOT_LOC)$(KERNEL_CONFIG); \
+ rm -f $(BUILD_ROOT_LOC)$(KERNEL_CONFIG); \
$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_HEADER_DEFCONFIG); \
$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) headers_install; fi
$(hide) if [ "$(KERNEL_HEADER_DEFCONFIG)" != "$(KERNEL_DEFCONFIG)" ]; then \
echo "Used a different defconfig for header generation"; \
- $(hide) rm -f $(BUILD_ROOT_LOC)$(KERNEL_CONFIG); \
+ rm -f $(BUILD_ROOT_LOC)$(KERNEL_CONFIG); \
$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_DEFCONFIG); fi
$(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
index 4dac20bcda69..34001a9ef4e8 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
@@ -18,13 +18,13 @@ Required properties
- qcom,sensor-id: The id of the TSENS sensor polled for temperature.
Typically the sensor closest to CPU0.
- qcom,poll-ms: Sampling interval to read sensor, in ms.
-- qcom,limit-temp: Threshold temperature to start stepping CPU down, in degC.
-- qcom,temp-hysteresis: Degrees C below threshold temperature to step CPU up.
-- qcom,freq-step: Number of frequency steps to take on each CPU mitigation.
Optional properties
- reg: Physical address for uio mapping
+- qcom,limit-temp: Threshold temperature to start stepping CPU down, in degC.
+- qcom,temp-hysteresis: Degrees C below threshold temperature to step CPU up.
+- qcom,freq-step: Number of frequency steps to take on each CPU mitigation.
- qcom,core-limit-temp: Threshold temperature to start shutting down cores
in degC
- qcom,core-temp-hysteresis: Degrees C below which the cores will be brought
diff --git a/Documentation/devicetree/bindings/cnss/icnss.txt b/Documentation/devicetree/bindings/cnss/icnss.txt
index 08fab81f3393..7857eeb963a6 100644
--- a/Documentation/devicetree/bindings/cnss/icnss.txt
+++ b/Documentation/devicetree/bindings/cnss/icnss.txt
@@ -12,6 +12,11 @@ Required properties:
- reg-names: Names of the memory regions defined in reg entry
- interrupts: Copy engine interrupt table
- qcom,wlan-msa-memory: MSA memory size
+ - clocks: List of clock phandles
+ - clock-names: List of clock names corresponding to the "clocks" property
+ - iommus: SMMUs and corresponding Stream IDs needed by WLAN
+ - qcom,wlan-smmu-iova-address: I/O virtual address range as <start length>
+ format to be used for allocations associated between WLAN and SMMU
Optional properties:
- qcom,skip-qmi: Boolean property to decide whether to use QMI or not
@@ -22,6 +27,11 @@ Example:
compatible = "qcom,icnss";
reg = <0x0a000000 0x1000000>;
reg-names = "membase";
+ clocks = <&clock_gcc clk_aggre2_noc_clk>;
+ clock-names = "smmu_aggre2_noc_clk";
+ iommus = <&anoc2_smmu 0x1900>,
+ <&anoc2_smmu 0x1901>;
+ qcom,wlan-smmu-iova-address = <0 0x10000000>;
interrupts =
<0 130 0 /* CE0 */ >,
<0 131 0 /* CE1 */ >,
diff --git a/Documentation/devicetree/bindings/iommu/iommu-debug.txt b/Documentation/devicetree/bindings/iommu/iommu-debug.txt
new file mode 100644
index 000000000000..1d79f1865aa5
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/iommu-debug.txt
@@ -0,0 +1,27 @@
+This document describes the device tree binding for IOMMU test devices.
+
+The iommu-debug framework can optionally make use of some platform devices
+for improved standalone testing and other features.
+
+- compatible: iommu-debug-test
+
+
+Required properties
+===================
+
+- iommus: The IOMMU for the test device (see iommu.txt)
+
+
+Example
+=======
+
+ iommu_test_device {
+ compatible = "iommu-debug-test";
+ /*
+ * 42 shouldn't be used by anyone on the cpp_fd_smmu. We just
+ * need _something_ here to get this node recognized by the
+ * SMMU driver. Our test uses ATOS, which doesn't use SIDs
+ * anyways, so using a dummy value is ok.
+ */
+ iommus = <&cpp_fd_smmu 42>;
+ };
diff --git a/Documentation/devicetree/bindings/media/video/msm-jpegdma.txt b/Documentation/devicetree/bindings/media/video/msm-jpegdma.txt
index 6b05e7fa3084..a1d604218219 100644
--- a/Documentation/devicetree/bindings/media/video/msm-jpegdma.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-jpegdma.txt
@@ -19,6 +19,8 @@ Required properties:
- clocks : clocks required for the device.
- qcom,clock-rates: should specify clock rates in Hz to each clocks
property defined.
+- qcom,max-ds-factor: should specify the max dma downscale factor,
+ supported by HW.
- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
below optional properties:
- qcom,msm-bus,name
@@ -67,5 +69,6 @@ Example:
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <62 512 0 0>,
<62 512 666675 666675>;
+ qcom,max-ds-factor = <128>;
status = "ok";
};
diff --git a/Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt b/Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt
index fc17085f5539..88a1c7d478c7 100644
--- a/Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt
@@ -109,7 +109,8 @@ KBSS specific properties:
Usage: optional
Value type: <u32>
The time in nanoseconds that the CPR controller must delay
- to allow voltage settling after a corner change.
+ to allow voltage settling per 1 mV of voltage change after a
+ corner change.
- qcom,cpr-hw-closed-loop
Usage: optional
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 6834ace0c778..8ec6be0dd1b1 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -4118,6 +4118,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
or other driver-specific files in the
Documentation/watchdog/ directory.
+ workqueue.watchdog_thresh=
+ If CONFIG_WQ_WATCHDOG is configured, workqueue can
+ warn stall conditions and dump internal state to
+ help debugging. 0 disables workqueue stall
+ detection; otherwise, it's the stall threshold
+ duration in seconds. The default value is 30 and
+ it can be updated at runtime by writing to the
+ corresponding sysfs file.
+
workqueue.disable_numa
By default, all work items queued to unbound
workqueues are affine to the NUMA nodes they're
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-8996.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-8996.dtsi
index e1c2dd8bde6a..cbe65e266968 100644
--- a/arch/arm/boot/dts/qcom/msm-arm-smmu-8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-8996.dtsi
@@ -251,3 +251,16 @@
"gcc_mmss_bimc_gfx_clk", "gcc_bimc_gfx_clk";
#clock-cells = <1>;
};
+
+&soc {
+ iommu_test_device {
+ compatible = "iommu-debug-test";
+ /*
+ * 42 shouldn't be used by anyone on the cpp_fd_smmu. We just
+ * need _something_ here to get this node recognized by the
+ * SMMU driver. Our test uses ATOS, which doesn't use SIDs
+ * anyways, so using a dummy value is ok.
+ */
+ iommus = <&cpp_fd_smmu 42>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi
index f00395b081b8..41af9b66d3c9 100644
--- a/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi
@@ -182,4 +182,15 @@
"gcc_gpu_bimc_gfx_clk";
#clock-cells = <1>;
};
+
+ iommu_test_device {
+ compatible = "iommu-debug-test";
+ /*
+ * 42 shouldn't be used by anyone on the mmss_smmu. We just
+ * need _something_ here to get this node recognized by the
+ * SMMU driver. Our test uses ATOS, which doesn't use SIDs
+ * anyways, so using a dummy value is ok.
+ */
+ iommus = <&mmss_smmu 42>;
+ };
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-cdp.dtsi
index e68f746bda38..f5d55972f92f 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-cdp.dtsi
@@ -61,6 +61,7 @@
&cam_actuator_vaf_suspend>;
pinctrl-1 = <&cam_actuator_vaf_active
&cam_actuator_vaf_suspend>;
+ status = "disabled";
};
eeprom0: qcom,eeprom@0 {
@@ -118,9 +119,9 @@
qcom,cam-vreg-op-mode = <0 80000 105000>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk2_active
+ pinctrl-0 = <&cam_sensor_mclk1_active
&cam_sensor_front_active>;
- pinctrl-1 = <&cam_sensor_mclk2_suspend
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
&cam_sensor_front_suspend>;
gpios = <&tlmm 14 0>,
<&tlmm 28 0>,
@@ -139,8 +140,8 @@
qcom,sensor-mode = <0>;
qcom,cci-master = <1>;
status = "ok";
- clocks = <&clock_mmss clk_mclk2_clk_src>,
- <&clock_mmss clk_mmss_camss_mclk2_clk>;
+ clocks = <&clock_mmss clk_mclk1_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk1_clk>;
clock-names = "cam_src_clk", "cam_clk";
qcom,clock-rates = <24000000 0>;
};
@@ -207,9 +208,9 @@
qcom,cam-vreg-op-mode = <0 0 80000>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk1_active
+ pinctrl-0 = <&cam_sensor_mclk2_active
&cam_sensor_rear2_active>;
- pinctrl-1 = <&cam_sensor_mclk1_suspend
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
&cam_sensor_rear2_suspend>;
gpios = <&tlmm 15 0>,
<&tlmm 9 0>,
@@ -225,8 +226,8 @@
qcom,sensor-mode = <0>;
qcom,cci-master = <0>;
status = "ok";
- clocks = <&clock_mmss clk_mclk1_clk_src>,
- <&clock_mmss clk_mmss_camss_mclk1_clk>;
+ clocks = <&clock_mmss clk_mclk2_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk2_clk>;
clock-names = "cam_src_clk", "cam_clk";
qcom,clock-rates = <24000000 0>;
};
@@ -251,9 +252,9 @@
qcom,cam-vreg-op-mode = <0 80000 105000>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk2_active
+ pinctrl-0 = <&cam_sensor_mclk1_active
&cam_sensor_front_active>;
- pinctrl-1 = <&cam_sensor_mclk2_suspend
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
&cam_sensor_front_suspend>;
gpios = <&tlmm 14 0>,
<&tlmm 28 0>,
@@ -272,8 +273,8 @@
qcom,sensor-mode = <0>;
qcom,cci-master = <1>;
status = "ok";
- clocks = <&clock_mmss clk_mclk2_clk_src>,
- <&clock_mmss clk_mmss_camss_mclk2_clk>;
+ clocks = <&clock_mmss clk_mclk1_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk1_clk>;
clock-names = "cam_src_clk", "cam_clk";
qcom,clock-rates = <24000000 0>;
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-mtp.dtsi
index e68f746bda38..f5d55972f92f 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-mtp.dtsi
@@ -61,6 +61,7 @@
&cam_actuator_vaf_suspend>;
pinctrl-1 = <&cam_actuator_vaf_active
&cam_actuator_vaf_suspend>;
+ status = "disabled";
};
eeprom0: qcom,eeprom@0 {
@@ -118,9 +119,9 @@
qcom,cam-vreg-op-mode = <0 80000 105000>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk2_active
+ pinctrl-0 = <&cam_sensor_mclk1_active
&cam_sensor_front_active>;
- pinctrl-1 = <&cam_sensor_mclk2_suspend
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
&cam_sensor_front_suspend>;
gpios = <&tlmm 14 0>,
<&tlmm 28 0>,
@@ -139,8 +140,8 @@
qcom,sensor-mode = <0>;
qcom,cci-master = <1>;
status = "ok";
- clocks = <&clock_mmss clk_mclk2_clk_src>,
- <&clock_mmss clk_mmss_camss_mclk2_clk>;
+ clocks = <&clock_mmss clk_mclk1_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk1_clk>;
clock-names = "cam_src_clk", "cam_clk";
qcom,clock-rates = <24000000 0>;
};
@@ -207,9 +208,9 @@
qcom,cam-vreg-op-mode = <0 0 80000>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk1_active
+ pinctrl-0 = <&cam_sensor_mclk2_active
&cam_sensor_rear2_active>;
- pinctrl-1 = <&cam_sensor_mclk1_suspend
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
&cam_sensor_rear2_suspend>;
gpios = <&tlmm 15 0>,
<&tlmm 9 0>,
@@ -225,8 +226,8 @@
qcom,sensor-mode = <0>;
qcom,cci-master = <0>;
status = "ok";
- clocks = <&clock_mmss clk_mclk1_clk_src>,
- <&clock_mmss clk_mmss_camss_mclk1_clk>;
+ clocks = <&clock_mmss clk_mclk2_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk2_clk>;
clock-names = "cam_src_clk", "cam_clk";
qcom,clock-rates = <24000000 0>;
};
@@ -251,9 +252,9 @@
qcom,cam-vreg-op-mode = <0 80000 105000>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk2_active
+ pinctrl-0 = <&cam_sensor_mclk1_active
&cam_sensor_front_active>;
- pinctrl-1 = <&cam_sensor_mclk2_suspend
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
&cam_sensor_front_suspend>;
gpios = <&tlmm 14 0>,
<&tlmm 28 0>,
@@ -272,8 +273,8 @@
qcom,sensor-mode = <0>;
qcom,cci-master = <1>;
status = "ok";
- clocks = <&clock_mmss clk_mclk2_clk_src>,
- <&clock_mmss clk_mmss_camss_mclk2_clk>;
+ clocks = <&clock_mmss clk_mclk1_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk1_clk>;
clock-names = "cam_src_clk", "cam_clk";
qcom,clock-rates = <24000000 0>;
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
index 4139bd1c70e0..c51069d1f571 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
@@ -16,7 +16,7 @@
compatible = "qcom,msm-cam";
reg = <0x8c0000 0x40000>;
reg-names = "msm-cam";
- status = "disabled";
+ status = "ok";
bus-vectors = "suspend", "svs", "nominal", "turbo";
qcom,bus-votes = <0 300000000 640000000 640000000>;
};
@@ -28,19 +28,28 @@
reg-names = "csiphy";
interrupts = <0 78 0>;
interrupt-names = "csiphy";
- clocks = <&clock_mmss clk_mmss_camss_top_ahb_clk>,
- <&clock_mmss clk_mmss_camss_ispif_ahb_clk>,
- <&clock_mmss clk_csi0phytimer_clk_src>,
- <&clock_mmss clk_mmss_camss_csi0phytimer_clk>,
+ clocks = <&clock_mmss clk_mmss_mnoc_maxi_clk>,
+ <&clock_mmss clk_mmss_mnoc_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>,
<&clock_mmss clk_mmss_camss_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_top_ahb_clk>,
<&clock_mmss clk_csi0_clk_src>,
<&clock_mmss clk_mmss_camss_csi0_clk>,
- <&clock_mmss clk_mmss_camss_cphy_csid0_clk>;
- clock-names = "camss_top_ahb_clk",
- "camss_ispif_ahb_clk", "csiphy_timer_src_clk",
- "csiphy_timer_clk", "camss_ahb_clk",
- "csi_src_clk", "csi_clk", "cphy_csid_clk";
- qcom,clock-rates = <0 0 269333333 0 0 256000000 0 0>;
+ <&clock_mmss clk_mmss_camss_cphy_csid0_clk>,
+ <&clock_mmss clk_csi0phytimer_clk_src>,
+ <&clock_mmss clk_mmss_camss_csi0phytimer_clk>,
+ <&clock_mmss clk_mmss_camss_ispif_ahb_clk>,
+ <&clock_mmss clk_csiphy_clk_src>,
+ <&clock_mmss clk_mmss_camss_csiphy0_clk>;
+ clock-names = "mnoc_maxi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "csi_src_clk", "csi_clk", "cphy_csid_clk",
+ "csiphy_timer_src_clk", "csiphy_timer_clk",
+ "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0
+ 0 256000000 0>;
};
qcom,csiphy@ca35000 {
@@ -50,19 +59,28 @@
reg-names = "csiphy";
interrupts = <0 79 0>;
interrupt-names = "csiphy";
- clocks = <&clock_mmss clk_mmss_camss_top_ahb_clk>,
- <&clock_mmss clk_mmss_camss_ispif_ahb_clk>,
- <&clock_mmss clk_csi1phytimer_clk_src>,
- <&clock_mmss clk_mmss_camss_csi1phytimer_clk>,
+ clocks = <&clock_mmss clk_mmss_mnoc_maxi_clk>,
+ <&clock_mmss clk_mmss_mnoc_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>,
<&clock_mmss clk_mmss_camss_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_top_ahb_clk>,
<&clock_mmss clk_csi1_clk_src>,
<&clock_mmss clk_mmss_camss_csi1_clk>,
- <&clock_mmss clk_mmss_camss_cphy_csid1_clk>;
- clock-names = "camss_top_ahb_clk",
- "camss_ispif_ahb_clk", "csiphy_timer_src_clk",
- "csiphy_timer_clk", "camss_ahb_clk",
- "csi_src_clk", "csi_clk", "cphy_csid_clk";
- qcom,clock-rates = <0 0 269333333 0 0 256000000 0 0>;
+ <&clock_mmss clk_mmss_camss_cphy_csid1_clk>,
+ <&clock_mmss clk_csi1phytimer_clk_src>,
+ <&clock_mmss clk_mmss_camss_csi1phytimer_clk>,
+ <&clock_mmss clk_mmss_camss_ispif_ahb_clk>,
+ <&clock_mmss clk_csiphy_clk_src>,
+ <&clock_mmss clk_mmss_camss_csiphy1_clk>;
+ clock-names = "mnoc_maxi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "csi_src_clk", "csi_clk", "cphy_csid_clk",
+ "csiphy_timer_src_clk", "csiphy_timer_clk",
+ "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0
+ 0 256000000 0>;
};
qcom,csiphy@ca36000 {
@@ -72,19 +90,28 @@
reg-names = "csiphy";
interrupts = <0 80 0>;
interrupt-names = "csiphy";
- clocks = <&clock_mmss clk_mmss_camss_top_ahb_clk>,
- <&clock_mmss clk_mmss_camss_ispif_ahb_clk>,
- <&clock_mmss clk_csi2phytimer_clk_src>,
- <&clock_mmss clk_mmss_camss_csi2phytimer_clk>,
+ clocks = <&clock_mmss clk_mmss_mnoc_maxi_clk>,
+ <&clock_mmss clk_mmss_mnoc_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>,
<&clock_mmss clk_mmss_camss_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_top_ahb_clk>,
<&clock_mmss clk_csi2_clk_src>,
<&clock_mmss clk_mmss_camss_csi2_clk>,
- <&clock_mmss clk_mmss_camss_cphy_csid2_clk>;
- clock-names = "camss_top_ahb_clk",
- "camss_ispif_ahb_clk", "csiphy_timer_src_clk",
- "csiphy_timer_clk", "camss_ahb_clk",
- "csi_src_clk", "csi_clk", "cphy_csid_clk";
- qcom,clock-rates = <0 0 269333333 0 0 256000000 0 0>;
+ <&clock_mmss clk_mmss_camss_cphy_csid2_clk>,
+ <&clock_mmss clk_csi2phytimer_clk_src>,
+ <&clock_mmss clk_mmss_camss_csi2phytimer_clk>,
+ <&clock_mmss clk_mmss_camss_ispif_ahb_clk>,
+ <&clock_mmss clk_csiphy_clk_src>,
+ <&clock_mmss clk_mmss_camss_csiphy2_clk>;
+ clock-names = "mnoc_maxi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "csi_src_clk", "csi_clk", "cphy_csid_clk",
+ "csiphy_timer_src_clk", "csiphy_timer_clk",
+ "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0
+ 0 256000000 0>;
};
qcom,csid@ca30000 {
@@ -94,24 +121,31 @@
reg-names = "csid";
interrupts = <0 296 0>;
interrupt-names = "csid";
- qcom,csi-vdd-voltage = <752000>;
- qcom,mipi-csi-vdd-supply = <&pmcobalt_s1_level>;
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pmcobalt_l2>;
gdscr-supply = <&gdsc_camss_top>;
- qcom,cam-vreg-name = "gdscr";
- clocks = <&clock_mmss clk_mmss_camss_top_ahb_clk>,
+ vdd_sec-supply = <&pmcobalt_l1>;
+ qcom,cam-vreg-name = "vdd_sec", "gdscr";
+ clocks = <&clock_mmss clk_mmss_mnoc_maxi_clk>,
+ <&clock_mmss clk_mmss_mnoc_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>,
+ <&clock_mmss clk_mmss_camss_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_top_ahb_clk>,
<&clock_mmss clk_mmss_camss_ispif_ahb_clk>,
<&clock_mmss clk_csi0_clk_src>,
<&clock_mmss clk_mmss_camss_csi0_clk>,
<&clock_mmss clk_mmss_camss_csiphy0_clk>,
<&clock_mmss clk_mmss_camss_csi0_ahb_clk>,
<&clock_mmss clk_mmss_camss_csi0rdi_clk>,
- <&clock_mmss clk_mmss_camss_csi0pix_clk>,
- <&clock_mmss clk_mmss_camss_ahb_clk>;
- clock-names = "camss_top_ahb_clk",
+ <&clock_mmss clk_mmss_camss_csi0pix_clk>;
+ clock-names = "mnoc_maxi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
"ispif_ahb_clk", "csi_src_clk", "csi_clk",
"csi_phy_clk", "csi_ahb_clk", "csi_rdi_clk",
- "csi_pix_clk", "camss_ahb_clk";
- qcom,clock-rates = <0 0 256000000 0 0 0 0 0 0>;
+ "csi_pix_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 0 256000000 0 0 0 0 0>;
status = "ok";
};
@@ -123,23 +157,30 @@
interrupts = <0 297 0>;
interrupt-names = "csid";
qcom,csi-vdd-voltage = <1200000>;
- qcom,mipi-csi-vdd-supply = <&pmcobalt_s1_level>;
+ qcom,mipi-csi-vdd-supply = <&pmcobalt_l2>;
gdscr-supply = <&gdsc_camss_top>;
- qcom,cam-vreg-name = "gdscr";
- clocks = <&clock_mmss clk_mmss_camss_top_ahb_clk>,
+ vdd_sec-supply = <&pmcobalt_l1>;
+ qcom,cam-vreg-name = "vdd_sec", "gdscr";
+ clocks = <&clock_mmss clk_mmss_mnoc_maxi_clk>,
+ <&clock_mmss clk_mmss_mnoc_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>,
+ <&clock_mmss clk_mmss_camss_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_top_ahb_clk>,
<&clock_mmss clk_mmss_camss_ispif_ahb_clk>,
<&clock_mmss clk_csi1_clk_src>,
<&clock_mmss clk_mmss_camss_csi1_clk>,
<&clock_mmss clk_mmss_camss_csiphy1_clk>,
<&clock_mmss clk_mmss_camss_csi1_ahb_clk>,
<&clock_mmss clk_mmss_camss_csi1rdi_clk>,
- <&clock_mmss clk_mmss_camss_csi1pix_clk>,
- <&clock_mmss clk_mmss_camss_ahb_clk>;
- clock-names = "camss_top_ahb_clk",
+ <&clock_mmss clk_mmss_camss_csi1pix_clk>;
+ clock-names = "mnoc_maxi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
"ispif_ahb_clk", "csi_src_clk", "csi_clk",
"csi_phy_clk", "csi_ahb_clk", "csi_rdi_clk",
- "csi_pix_clk", "camss_ahb_clk";
- qcom,clock-rates = <0 0 256000000 0 0 0 0 0 0>;
+ "csi_pix_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 0 256000000 0 0 0 0 0>;
};
qcom,csid@ca30800 {
@@ -150,23 +191,30 @@
interrupts = <0 298 0>;
interrupt-names = "csid";
qcom,csi-vdd-voltage = <1200000>;
- qcom,mipi-csi-vdd-supply = <&pmcobalt_s1_level>;
+ qcom,mipi-csi-vdd-supply = <&pmcobalt_l2>;
gdscr-supply = <&gdsc_camss_top>;
- qcom,cam-vreg-name = "gdscr";
- clocks = <&clock_mmss clk_mmss_camss_top_ahb_clk>,
+ vdd_sec-supply = <&pmcobalt_l1>;
+ qcom,cam-vreg-name = "vdd_sec", "gdscr";
+ clocks = <&clock_mmss clk_mmss_mnoc_maxi_clk>,
+ <&clock_mmss clk_mmss_mnoc_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>,
+ <&clock_mmss clk_mmss_camss_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_top_ahb_clk>,
<&clock_mmss clk_mmss_camss_ispif_ahb_clk>,
<&clock_mmss clk_csi2_clk_src>,
<&clock_mmss clk_mmss_camss_csi2_clk>,
<&clock_mmss clk_mmss_camss_csiphy2_clk>,
<&clock_mmss clk_mmss_camss_csi2_ahb_clk>,
<&clock_mmss clk_mmss_camss_csi2rdi_clk>,
- <&clock_mmss clk_mmss_camss_csi2pix_clk>,
- <&clock_mmss clk_mmss_camss_ahb_clk>;
- clock-names = "camss_top_ahb_clk",
+ <&clock_mmss clk_mmss_camss_csi2pix_clk>;
+ clock-names = "mnoc_maxi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
"ispif_ahb_clk", "csi_src_clk", "csi_clk",
"csi_phy_clk", "csi_ahb_clk", "csi_rdi_clk",
- "csi_pix_clk", "camss_ahb_clk";
- qcom,clock-rates = <0 0 256000000 0 0 0 0 0 0>;
+ "csi_pix_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 0 256000000 0 0 0 0 0>;
};
qcom,csid@ca30c00 {
@@ -177,27 +225,33 @@
interrupts = <0 299 0>;
interrupt-names = "csid";
qcom,csi-vdd-voltage = <1200000>;
- qcom,mipi-csi-vdd-supply = <&pmcobalt_s1_level>;
+ qcom,mipi-csi-vdd-supply = <&pmcobalt_l2>;
gdscr-supply = <&gdsc_camss_top>;
- qcom,cam-vreg-name = "gdscr";
- clocks = <&clock_mmss clk_mmss_camss_top_ahb_clk>,
+ vdd_sec-supply = <&pmcobalt_l1>;
+ qcom,cam-vreg-name = "vdd_sec", "gdscr";
+ clocks = <&clock_mmss clk_mmss_mnoc_maxi_clk>,
+ <&clock_mmss clk_mmss_mnoc_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>,
+ <&clock_mmss clk_mmss_camss_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_top_ahb_clk>,
<&clock_mmss clk_mmss_camss_ispif_ahb_clk>,
- <&clock_mmss clk_csi0_clk_src>,
- <&clock_mmss clk_mmss_camss_csi0_clk>,
- <&clock_mmss clk_mmss_camss_csiphy0_clk>,
- <&clock_mmss clk_mmss_camss_csi0_ahb_clk>,
- <&clock_mmss clk_mmss_camss_csi0rdi_clk>,
- <&clock_mmss clk_mmss_camss_csi0pix_clk>,
- <&clock_mmss clk_mmss_camss_ahb_clk>;
- clock-names = "camss_top_ahb_clk",
+ <&clock_mmss clk_csi3_clk_src>,
+ <&clock_mmss clk_mmss_camss_csi3_clk>,
+ <&clock_mmss clk_mmss_camss_csi3_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_csi3rdi_clk>,
+ <&clock_mmss clk_mmss_camss_csi3pix_clk>;
+ clock-names = "mnoc_maxi", "mnoc_ahb",
+ "bmic_smmu_ahb", "bmic_smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
"ispif_ahb_clk", "csi_src_clk", "csi_clk",
- "csi_phy_clk", "csi_ahb_clk", "csi_rdi_clk",
- "csi_pix_clk", "camss_ahb_clk";
- qcom,clock-rates = <0 0 256000000 0 0 0 0 0 0>;
+ "csi_ahb_clk", "csi_rdi_clk",
+ "csi_pix_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 0 256000000 0 0 0 0>;
};
qcom,cam_smmu {
compatible = "qcom,msm-cam-smmu";
- status = "disabled";
+ status = "ok";
msm_cam_smmu_cb1 {
compatible = "qcom,msm-cam-smmu-cb";
@@ -605,16 +659,20 @@
mmagic-supply = <&gdsc_bimc_smmu>;
gdscr-supply = <&gdsc_camss_top>;
qcom,cam-vreg-name = "mmagic", "gdscr";
- clocks = <&clock_mmss clk_mmss_camss_top_ahb_clk>,
+ clocks = <&clock_mmss clk_mmss_mnoc_maxi_clk>,
+ <&clock_mmss clk_mmss_mnoc_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_ahb_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>,
+ <&clock_mmss clk_mmss_camss_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_top_ahb_clk>,
<&clock_mmss clk_cci_clk_src>,
<&clock_mmss clk_mmss_camss_cci_ahb_clk>,
- <&clock_mmss clk_mmss_camss_cci_clk>,
- <&clock_mmss clk_mmss_camss_ahb_clk>;
- clock-names = "camss_top_ahb_clk",
- "cci_src_clk", "cci_ahb_clk", "camss_cci_clk",
- "camss_ahb_clk";
- qcom,clock-rates = <0 19200000 0 0 0>,
- <0 37500000 0 0 0>;
+ <&clock_mmss clk_mmss_camss_cci_clk>;
+ clock-names = "mnoc_axi", "mnoc_ahb", "smmu_ahb", "smmu_axi",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "cci_src_clk", "cci_ahb_clk", "camss_cci_clk";
+ qcom,clock-rates = <0 0 0 0 0 0 19200000 0 0>,
+ <0 0 0 0 0 0 37500000 0 0>;
pinctrl-names = "cci_default", "cci_suspend";
pinctrl-0 = <&cci0_active &cci1_active>;
pinctrl-1 = <&cci0_suspend &cci1_suspend>;
@@ -725,6 +783,7 @@
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <62 512 0 0>,
<62 512 666675 666675>;
+ qcom,max-ds-factor = <128>;
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
index f72dfacbc70d..dcadd99e2f2e 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
@@ -61,11 +61,6 @@
vcc-max-microamp = <750000>;
vccq-max-microamp = <560000>;
vccq2-max-microamp = <750000>;
-
- qcom,disable-lpm;
- rpm-level = <0>;
- spm-level = <0>;
-
status = "ok";
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
index 929c48c7346c..fd7e0404691c 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
@@ -75,6 +75,8 @@
qcom,deep-nap-timeout = <2>; //<HZ/50>
qcom,strtstp-sleepwake;
+ qcom,highest-bank-bit = <15>;
+
clocks = <&clock_gfx clk_gpucc_gfx3d_clk>,
<&clock_gcc clk_gcc_gpu_cfg_ahb_clk>,
<&clock_gpu clk_gpucc_rbbmtimer_clk>,
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
index 7bae6848c61c..d72a770d886e 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
@@ -61,11 +61,6 @@
vcc-max-microamp = <750000>;
vccq-max-microamp = <560000>;
vccq2-max-microamp = <750000>;
-
- qcom,disable-lpm;
- rpm-level = <0>;
- spm-level = <0>;
-
status = "ok";
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
index 03b8aa094796..9acbeae79a28 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
@@ -746,12 +746,12 @@
cam_sensor_rear_active: cam_sensor_rear_active {
/* RESET, STANDBY */
mux {
- pins = "gpio30","gpio29","gpio27";
+ pins = "gpio30","gpio29";
function = "gpio";
};
config {
- pins = "gpio30","gpio29","gpio27";
+ pins = "gpio30","gpio29";
bias-disable; /* No PULL */
drive-strength = <2>; /* 2 MA */
};
@@ -1011,12 +1011,12 @@
cam_sensor_rear_suspend: cam_sensor_rear_suspend {
/* RESET, STANDBY */
mux {
- pins = "gpio30","gpio29","gpio27";
+ pins = "gpio30","gpio29";
function = "gpio";
};
config {
- pins = "gpio30","gpio29","gpio27";
+ pins = "gpio30","gpio29";
bias-disable; /* No PULL */
drive-strength = <2>; /* 2 MA */
};
@@ -1055,12 +1055,12 @@
cam_sensor_rear2_active: cam_sensor_rear2_active {
/* RESET, STANDBY */
mux {
- pins = "gpio63","gpio62";
+ pins = "gpio9","gpio8";
function = "gpio";
};
config {
- pins = "gpio63","gpio62";
+ pins = "gpio9","gpio8";
bias-disable; /* No PULL */
drive-strength = <2>; /* 2 MA */
};
@@ -1118,19 +1118,16 @@
};
};
- cam_sensor_rear2_sus {
- cam_sensor_rear2_suspend: cam_sensor_rear2_suspend {
- /* RESET, STANDBY */
- mux {
- pins = "gpio63","gpio62";
- function = "gpio";
- };
-
- config {
- pins = "gpio63","gpio62";
- bias-disable; /* No PULL */
- drive-strength = <2>; /* 2 MA */
- };
+ cam_sensor_rear2_suspend: cam_sensor_rear2_suspend {
+ /* RESET, STANDBY */
+ mux {
+ pins = "gpio9","gpio8";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio9","gpio8";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
};
};
@@ -1167,12 +1164,12 @@
cam_sensor_front_active: cam_sensor_front_active {
/* RESET, STANDBY */
mux {
- pins = "gpio23","gpio26";
+ pins = "gpio28","gpio27";
function = "gpio";
};
config {
- pins = "gpio23","gpio26";
+ pins = "gpio28","gpio27";
bias-disable; /* No PULL */
drive-strength = <2>; /* 2 MA */
};
@@ -1233,12 +1230,12 @@
cam_sensor_front_suspend: cam_sensor_front_suspend {
/* RESET, STANDBY */
mux {
- pins = "gpio23","gpio26";
+ pins = "gpio28","gpio27";
function = "gpio";
};
config {
- pins = "gpio23","gpio26";
+ pins = "gpio28","gpio27";
bias-disable; /* No PULL */
drive-strength = <2>; /* 2 MA */
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
index 89134821899b..0490ce3854cd 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
@@ -599,11 +599,11 @@
qcom,cpr-up-down-delay-time = <3000>;
qcom,cpr-step-quot-init-min = <11>;
qcom,cpr-step-quot-init-max = <13>;
- qcom,cpr-count-mode = <2>; /* Staggered */
+ qcom,cpr-count-mode = <0>; /* All at once */
qcom,cpr-down-error-step-limit = <1>;
qcom,cpr-up-error-step-limit = <1>;
- qcom,cpr-corner-switch-delay-time = <1600>;
- qcom,cpr-voltage-settling-time = <1600>;
+ qcom,cpr-corner-switch-delay-time = <209>;
+ qcom,cpr-voltage-settling-time = <1760>;
qcom,apm-threshold-voltage = <832000>;
qcom,apm-hysteresis-voltage = <32000>;
@@ -611,11 +611,14 @@
qcom,voltage-base = <352000>;
qcom,cpr-saw-use-unit-mV;
+ qcom,cpr-enable;
+ qcom,cpr-hw-closed-loop;
+
thread@0 {
qcom,cpr-thread-id = <0>;
qcom,cpr-consecutive-up = <0>;
- qcom,cpr-consecutive-down = <2>;
- qcom,cpr-up-threshold = <0>;
+ qcom,cpr-consecutive-down = <0>;
+ qcom,cpr-up-threshold = <2>;
qcom,cpr-down-threshold = <2>;
apc0_pwrcl_vreg: regulator-pwrcl {
@@ -685,11 +688,11 @@
qcom,cpr-up-down-delay-time = <3000>;
qcom,cpr-step-quot-init-min = <11>;
qcom,cpr-step-quot-init-max = <13>;
- qcom,cpr-count-mode = <2>; /* Staggered */
+ qcom,cpr-count-mode = <0>; /* All at once */
qcom,cpr-down-error-step-limit = <1>;
qcom,cpr-up-error-step-limit = <1>;
- qcom,cpr-corner-switch-delay-time = <1600>;
- qcom,cpr-voltage-settling-time = <1600>;
+ qcom,cpr-corner-switch-delay-time = <209>;
+ qcom,cpr-voltage-settling-time = <1760>;
qcom,apm-threshold-voltage = <832000>;
qcom,apm-hysteresis-voltage = <32000>;
@@ -697,11 +700,14 @@
qcom,voltage-base = <352000>;
qcom,cpr-saw-use-unit-mV;
+ qcom,cpr-enable;
+ qcom,cpr-hw-closed-loop;
+
thread@0 {
qcom,cpr-thread-id = <0>;
qcom,cpr-consecutive-up = <0>;
- qcom,cpr-consecutive-down = <2>;
- qcom,cpr-up-threshold = <0>;
+ qcom,cpr-consecutive-down = <0>;
+ qcom,cpr-up-threshold = <2>;
qcom,cpr-down-threshold = <2>;
apc1_perfcl_vreg: regulator-pwrcl {
@@ -776,13 +782,15 @@
qcom,cpr-idle-cycles = <15>;
qcom,cpr-step-quot-init-min = <10>;
qcom,cpr-step-quot-init-max = <13>;
- qcom,cpr-count-mode = <2>; /* Staggered */
+ qcom,cpr-count-mode = <0>; /* All-at-once min */
vdd-supply = <&pm8005_s1>;
qcom,voltage-step = <4000>;
mem-acc-supply = <&gfx_mem_acc_vreg>;
qcom,cpr-aging-ref-voltage = <1032000>;
+ qcom,cpr-enable;
+
thread@0 {
qcom,cpr-thread-id = <0>;
qcom,cpr-consecutive-up = <0>;
@@ -842,11 +850,39 @@
<2389 2287 2985 3112 2873 2904 2159 2399
1580 1602 2158 3042 2780 2069 0 0>;
+ qcom,cpr-open-loop-voltage-fuse-adjustment =
+ < 0 0 0 0>,
+ < 0 0 0 0>,
+ < 0 0 0 0>,
+ < 0 0 0 0>,
+ < 0 0 0 0>,
+ < 0 0 0 0>,
+ < 0 0 0 0>,
+ < 0 0 0 0>;
+
+ qcom,cpr-closed-loop-voltage-adjustment =
+ < 150000 150000 150000 150000
+ 150000 150000>,
+ < 150000 150000 150000 150000
+ 150000 150000>,
+ < 150000 150000 150000 150000
+ 150000 150000>,
+ < 150000 150000 150000 150000
+ 150000 150000>,
+ < 150000 150000 150000 150000
+ 150000 150000>,
+ < 150000 150000 150000 150000
+ 150000 150000>,
+ < 150000 150000 150000 150000
+ 150000 150000>,
+ < 150000 150000 150000 150000
+ 150000 150000>;
+
qcom,cpr-floor-to-ceiling-max-range =
<50000 50000 50000 50000 50000 50000>;
qcom,cpr-fused-closed-loop-voltage-adjustment-map =
- <1 2 2 3 3 4>;
+ <0 0 1 2 3 4>;
qcom,allow-voltage-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index 78c99ee81a12..4e2c4b732c05 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -629,10 +629,16 @@
reg = <0xc8c0000 0x40000>;
reg-names = "cc_base";
vdd_dig-supply = <&pmcobalt_s1_level>;
- clock-names = "xo", "gpll0", "gpll0_div";
+ clock-names = "xo", "gpll0", "gpll0_div",
+ "pclk0_src", "pclk1_src",
+ "byte0_src", "byte1_src";
clocks = <&clock_gcc clk_cxo_clk_src>,
<&clock_gcc clk_gpll0_out_main>,
- <&clock_gcc clk_gcc_mmss_gpll0_div_clk>;
+ <&clock_gcc clk_gcc_mmss_gpll0_div_clk>,
+ <&mdss_dsi0_pll clk_dsi0pll_pclk_mux>,
+ <&mdss_dsi1_pll clk_dsi1pll_pclk_mux>,
+ <&mdss_dsi0_pll clk_dsi0pll_byteclk_mux>,
+ <&mdss_dsi1_pll clk_dsi1pll_byteclk_mux>;
#clock-cells = <1>;
};
@@ -1927,16 +1933,18 @@
qcom,proxy-reg-names = "vdd";
clocks = <&clock_mmss clk_mmss_video_core_clk>,
+ <&clock_mmss clk_mmss_mnoc_ahb_clk>,
<&clock_mmss clk_mmss_video_ahb_clk>,
+ <&clock_gcc clk_mmssnoc_axi_clk>,
<&clock_mmss clk_mmss_video_axi_clk>,
<&clock_mmss clk_mmss_video_maxi_clk>;
- clock-names = "core_clk", "iface_clk",
- "bus_clk", "maxi_clk";
- qcom,proxy-clock-names = "core_clk", "iface_clk",
- "bus_clk", "maxi_clk";
+ clock-names = "core_clk", "mnoc_ahb_clk", "iface_clk",
+ "noc_axi_clk", "bus_clk", "maxi_clk";
+ qcom,proxy-clock-names = "core_clk","mnoc_ahb_clk",
+ "iface_clk", "noc_axi_clk", "bus_clk", "maxi_clk";
qcom,pas-id = <9>;
- qcom,proxy-timeout-ms = <100>;
+ qcom,proxy-timeout-ms = <10000>;
qcom,firmware-name = "venus";
memory-region = <&peripheral_mem>;
status = "ok";
@@ -1986,11 +1994,6 @@
qcom,rtb-size = <0x100000>;
};
- qcom,msm-rtb {
- compatible = "qcom,msm-rtb";
- qcom,rtb-size = <0x100000>;
- };
-
qcom,msm-imem@146bf000 {
compatible = "qcom,msm-imem";
reg = <0x146bf000 0x1000>;
@@ -2017,6 +2020,11 @@
compatible = "qcom,msm-imem-pil";
reg = <0x94c 200>;
};
+
+ diag_dload@c8 {
+ compatible = "qcom,msm-imem-diag-dload";
+ reg = <0xc8 200>;
+ };
};
cpu_pmu: cpu-pmu {
@@ -2144,6 +2152,11 @@
reg = <0x18800000 0x800000>,
<0x10AC000 0x20>;
reg-names = "membase", "mpm_config";
+ clocks = <&clock_gcc clk_aggre2_noc_clk>;
+ clock-names = "smmu_aggre2_noc_clk";
+ iommus = <&anoc2_smmu 0x1900>,
+ <&anoc2_smmu 0x1901>;
+ qcom,wlan-smmu-iova-address = <0xa0000000 0x10000000>;
interrupts = <0 413 0 /* CE0 */ >,
<0 414 0 /* CE1 */ >,
<0 415 0 /* CE2 */ >,
diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig
index d780a12b161c..6b3d8718fe50 100644
--- a/arch/arm64/configs/msm_defconfig
+++ b/arch/arm64/configs/msm_defconfig
@@ -523,6 +523,7 @@ CONFIG_MSM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_ARM_SMMU=y
CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
CONFIG_IOMMU_TESTS=y
CONFIG_MSM_SMEM=y
CONFIG_QPNP_HAPTIC=y
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 5134ffe9a6a0..7cc9914a671e 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -216,6 +216,7 @@ CONFIG_MSM_BT_POWER=y
CONFIG_BTFM_SLIM=y
CONFIG_BTFM_SLIM_WCN3990=y
CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
CONFIG_RFKILL=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
@@ -285,7 +286,6 @@ CONFIG_DIAG_CHAR=y
CONFIG_VIRTIO_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_MSM_ADSPRPC=y
-CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MSM_V2=y
CONFIG_SLIMBUS=y
@@ -325,6 +325,9 @@ CONFIG_REGULATOR_CPRH_KBSS=y
CONFIG_REGULATOR_MEM_ACC=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MSM_SDE_ROTATOR=y
CONFIG_FB=y
CONFIG_FB_ARMCLCD=y
CONFIG_FB_MSM=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index 4c851ce0168d..e14f310f7125 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -215,6 +215,8 @@ CONFIG_MSM_BT_POWER=y
CONFIG_BTFM_SLIM=y
CONFIG_BTFM_SLIM_WCN3990=y
CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+# CONFIG_CFG80211_CRDA_SUPPORT is not set
CONFIG_RFKILL=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
@@ -298,7 +300,6 @@ CONFIG_DIAG_CHAR=y
CONFIG_VIRTIO_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_MSM_ADSPRPC=y
-CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MSM_V2=y
CONFIG_SLIMBUS=y
@@ -338,6 +339,9 @@ CONFIG_REGULATOR_CPRH_KBSS=y
CONFIG_REGULATOR_MEM_ACC=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MSM_SDE_ROTATOR=y
CONFIG_QCOM_KGSL=y
CONFIG_FB=y
CONFIG_FB_ARMCLCD=y
@@ -461,6 +465,7 @@ CONFIG_MSM_SMP2P_TEST=y
CONFIG_MSM_QMI_INTERFACE=y
CONFIG_MSM_RPM_SMD=y
CONFIG_QCOM_BUS_SCALING=y
+CONFIG_MSM_SERVICE_LOCATOR=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_SYSMON_GLINK_COMM=y
CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
@@ -484,6 +489,7 @@ CONFIG_TRACER_PKT=y
CONFIG_MSM_MPM_OF=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_CORE_CTL_HELPER=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_EXTCON=y
CONFIG_PWM=y
@@ -522,7 +528,9 @@ CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_PAGE_OWNER=y
+CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
CONFIG_SLUB_DEBUG_PANIC_ON=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_FREE=y
@@ -537,6 +545,7 @@ CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_LOCKUP_DETECTOR=y
+CONFIG_WQ_WATCHDOG=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
diff --git a/drivers/clk/msm/clock-gcc-cobalt.c b/drivers/clk/msm/clock-gcc-cobalt.c
index 88d77977235d..ec06e6b9774f 100644
--- a/drivers/clk/msm/clock-gcc-cobalt.c
+++ b/drivers/clk/msm/clock-gcc-cobalt.c
@@ -261,6 +261,7 @@ static struct rcg_clk pcie_aux_clk_src = {
};
static struct clk_freq_tbl ftbl_ufs_axi_clk_src[] = {
+ F( 50000000, gpll0_out_main, 12, 0, 0),
F( 100000000, gpll0_out_main, 6, 0, 0),
F( 200000000, gpll0_out_main, 3, 0, 0),
F( 240000000, gpll0_out_main, 2.5, 0, 0),
@@ -916,6 +917,7 @@ static struct rcg_clk tsif_ref_clk_src = {
};
static struct clk_freq_tbl ftbl_ufs_ice_core_clk_src[] = {
+ F( 75000000, gpll0_out_main, 8, 0, 0),
F( 150000000, gpll0_out_main, 4, 0, 0),
F( 300000000, gpll0_out_main, 2, 0, 0),
F_END
@@ -1168,6 +1170,7 @@ static struct branch_clk gcc_bimc_mss_q6_axi_clk = {
static struct local_vote_clk gcc_blsp1_ahb_clk = {
.cbcr_reg = GCC_BLSP1_AHB_CBCR,
+ .bcr_reg = GCC_BLSP1_BCR,
.vote_reg = GCC_APCS_CLOCK_BRANCH_ENA_VOTE,
.en_mask = BIT(17),
.base = &virt_base,
@@ -1360,6 +1363,7 @@ static struct branch_clk gcc_blsp1_uart3_apps_clk = {
static struct local_vote_clk gcc_blsp2_ahb_clk = {
.cbcr_reg = GCC_BLSP2_AHB_CBCR,
+ .bcr_reg = GCC_BLSP2_BCR,
.vote_reg = GCC_APCS_CLOCK_BRANCH_ENA_VOTE,
.en_mask = BIT(15),
.base = &virt_base,
@@ -1958,6 +1962,7 @@ static struct branch_clk gcc_ufs_ahb_clk = {
static struct branch_clk gcc_ufs_axi_clk = {
.cbcr_reg = GCC_UFS_AXI_CBCR,
+ .bcr_reg = GCC_UFS_BCR,
.has_sibling = 0,
.base = &virt_base,
.c = {
diff --git a/drivers/edac/cortex_arm64_edac.c b/drivers/edac/cortex_arm64_edac.c
index 2268bd3fa8f0..1fa8e9a62082 100644
--- a/drivers/edac/cortex_arm64_edac.c
+++ b/drivers/edac/cortex_arm64_edac.c
@@ -267,8 +267,10 @@ static void ca53_parse_cpumerrsr(struct erp_local_data *ed)
if (A53_CPUMERRSR_FATAL(cpumerrsr))
ed->err = DBE;
- edac_printk(KERN_CRIT, EDAC_CPU, "Cortex A53 CPU%d L1 %s Error detected\n",
- smp_processor_id(), err_name[ed->err]);
+ edac_printk(KERN_CRIT, EDAC_CPU,
+ "Kryo2xx Silver CPU%d L1 %s Error detected\n",
+ smp_processor_id(), err_name[ed->err]);
+
ca53_ca57_print_error_state_regs();
if (ed->err == DBE)
edac_printk(KERN_CRIT, EDAC_CPU, "Fatal error\n");
@@ -338,8 +340,8 @@ static void ca53_parse_l2merrsr(struct erp_local_data *ed)
if (A53_L2MERRSR_FATAL(l2merrsr))
ed->err = DBE;
- edac_printk(KERN_CRIT, EDAC_CPU, "CortexA53 L2 %s Error detected\n",
- err_name[ed->err]);
+ edac_printk(KERN_CRIT, EDAC_CPU, "Kyro2xx Silver L2 %s Error detected\n",
+ err_name[ed->err]);
ca53_ca57_print_error_state_regs();
if (ed->err == DBE)
edac_printk(KERN_CRIT, EDAC_CPU, "Fatal error\n");
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index 0ad87c609453..db5a9ca28408 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -10,7 +10,8 @@ msm_kgsl_core-y = \
kgsl_pwrscale.o \
kgsl_mmu.o \
kgsl_snapshot.o \
- kgsl_events.o
+ kgsl_events.o \
+ kgsl_pool.o
msm_kgsl_core-$(CONFIG_QCOM_KGSL_IOMMU) += kgsl_iommu.o
msm_kgsl_core-$(CONFIG_DEBUG_FS) += kgsl_debugfs.o
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index d8f94757ba28..fd972dfd3862 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -44,35 +44,20 @@
/* CP_EVENT_WRITE events */
#define CACHE_FLUSH_TS 4
-/* CP_INTERRUPT masks */
-
-#define CP_INTERRUPT_IB2 0x20000000
-#define CP_INTERRUPT_IB1 0x40000000
-#define CP_INTERRUPT_RB 0x80000000
-
/* Register definitions */
-#define A3XX_RBBM_HW_VERSION 0x000
-#define A3XX_RBBM_HW_RELEASE 0x001
-#define A3XX_RBBM_HW_CONFIGURATION 0x002
#define A3XX_RBBM_CLOCK_CTL 0x010
#define A3XX_RBBM_SP_HYST_CNT 0x012
#define A3XX_RBBM_SW_RESET_CMD 0x018
#define A3XX_RBBM_AHB_CTL0 0x020
#define A3XX_RBBM_AHB_CTL1 0x021
#define A3XX_RBBM_AHB_CMD 0x022
-#define A3XX_RBBM_AHB_ME_SPLIT_STATUS 0x25
-#define A3XX_RBBM_AHB_PFP_SPLIT_STATUS 0x26
#define A3XX_RBBM_AHB_ERROR_STATUS 0x027
#define A3XX_RBBM_GPR0_CTL 0x02E
/* This the same register as on A2XX, just in a different place */
#define A3XX_RBBM_STATUS 0x030
#define A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL 0x33
#define A3XX_RBBM_INTERFACE_HANG_INT_CTL 0x50
-#define A3XX_RBBM_INTERFACE_HANG_MASK_CTL0 0x51
-#define A3XX_RBBM_INTERFACE_HANG_MASK_CTL1 0x54
-#define A3XX_RBBM_INTERFACE_HANG_MASK_CTL2 0x57
-#define A3XX_RBBM_INTERFACE_HANG_MASK_CTL3 0x5A
#define A3XX_RBBM_INT_CLEAR_CMD 0x061
#define A3XX_RBBM_INT_0_MASK 0x063
#define A3XX_RBBM_INT_0_STATUS 0x064
@@ -188,10 +173,8 @@
#define A3XX_RBBM_EXT_TRACE_CMD 0x122
#define A3XX_CP_RB_BASE 0x01C0
#define A3XX_CP_RB_CNTL 0x01C1
-#define A3XX_CP_RB_RPTR_ADDR 0x01C3
#define A3XX_CP_RB_RPTR 0x01C4
#define A3XX_CP_RB_WPTR 0x01C5
-#define A3XX_CP_RB_RPTR_WR 0x01C7
/* Following two are same as on A2XX, just in a different place */
#define A3XX_CP_PFP_UCODE_ADDR 0x1C9
#define A3XX_CP_PFP_UCODE_DATA 0x1CA
@@ -203,8 +186,6 @@
#define A3XX_CP_QUEUE_THRESHOLDS 0x01D5
#define A3XX_CP_MEQ_ADDR 0x1DA
#define A3XX_CP_MEQ_DATA 0x1DB
-#define A3XX_CP_SCRATCH_UMSK 0x01DC
-#define A3XX_CP_SCRATCH_ADDR 0x01DD
#define A3XX_CP_STATE_DEBUG_INDEX 0x01EC
#define A3XX_CP_STATE_DEBUG_DATA 0x01ED
#define A3XX_CP_CNTL 0x01F4
@@ -225,53 +206,28 @@
#define A3XX_CP_IB2_BUFSZ 0x045B
#define A3XX_CP_HW_FAULT 0x45C
-#define A3XX_CP_AHB_FAULT 0x54D
#define A3XX_CP_PROTECT_CTRL 0x45E
#define A3XX_CP_PROTECT_STATUS 0x45F
#define A3XX_CP_PROTECT_REG_0 0x460
-#define A3XX_CP_PROTECT_REG_1 0x461
-#define A3XX_CP_PROTECT_REG_2 0x462
-#define A3XX_CP_PROTECT_REG_3 0x463
-#define A3XX_CP_PROTECT_REG_4 0x464
-#define A3XX_CP_PROTECT_REG_5 0x465
-#define A3XX_CP_PROTECT_REG_6 0x466
-#define A3XX_CP_PROTECT_REG_7 0x467
-#define A3XX_CP_PROTECT_REG_8 0x468
-#define A3XX_CP_PROTECT_REG_9 0x469
-#define A3XX_CP_PROTECT_REG_A 0x46A
-#define A3XX_CP_PROTECT_REG_B 0x46B
-#define A3XX_CP_PROTECT_REG_C 0x46C
-#define A3XX_CP_PROTECT_REG_D 0x46D
-#define A3XX_CP_PROTECT_REG_E 0x46E
-#define A3XX_CP_PROTECT_REG_F 0x46F
#define A3XX_CP_STAT 0x047F
#define A3XX_CP_SCRATCH_REG0 0x578
#define A3XX_CP_SCRATCH_REG6 0x57E
#define A3XX_CP_SCRATCH_REG7 0x57F
-#define A3XX_VSC_BIN_SIZE 0xC01
#define A3XX_VSC_SIZE_ADDRESS 0xC02
-#define A3XX_VSC_PIPE_CONFIG_0 0xC06
#define A3XX_VSC_PIPE_DATA_ADDRESS_0 0xC07
#define A3XX_VSC_PIPE_DATA_LENGTH_0 0xC08
-#define A3XX_VSC_PIPE_CONFIG_1 0xC09
#define A3XX_VSC_PIPE_DATA_ADDRESS_1 0xC0A
#define A3XX_VSC_PIPE_DATA_LENGTH_1 0xC0B
-#define A3XX_VSC_PIPE_CONFIG_2 0xC0C
#define A3XX_VSC_PIPE_DATA_ADDRESS_2 0xC0D
#define A3XX_VSC_PIPE_DATA_LENGTH_2 0xC0E
-#define A3XX_VSC_PIPE_CONFIG_3 0xC0F
#define A3XX_VSC_PIPE_DATA_ADDRESS_3 0xC10
#define A3XX_VSC_PIPE_DATA_LENGTH_3 0xC11
-#define A3XX_VSC_PIPE_CONFIG_4 0xC12
#define A3XX_VSC_PIPE_DATA_ADDRESS_4 0xC13
#define A3XX_VSC_PIPE_DATA_LENGTH_4 0xC14
-#define A3XX_VSC_PIPE_CONFIG_5 0xC15
#define A3XX_VSC_PIPE_DATA_ADDRESS_5 0xC16
#define A3XX_VSC_PIPE_DATA_LENGTH_5 0xC17
-#define A3XX_VSC_PIPE_CONFIG_6 0xC18
#define A3XX_VSC_PIPE_DATA_ADDRESS_6 0xC19
#define A3XX_VSC_PIPE_DATA_LENGTH_6 0xC1A
-#define A3XX_VSC_PIPE_CONFIG_7 0xC1B
#define A3XX_VSC_PIPE_DATA_ADDRESS_7 0xC1C
#define A3XX_VSC_PIPE_DATA_LENGTH_7 0xC1D
#define A3XX_PC_PERFCOUNTER0_SELECT 0xC48
@@ -417,10 +373,6 @@
#define A3XX_RB_SAMPLE_COUNT_ADDR 0x2111
#define A3XX_RB_Z_CLAMP_MIN 0x2114
#define A3XX_RB_Z_CLAMP_MAX 0x2115
-#define A3XX_PC_VSTREAM_CONTROL 0x21E4
-#define A3XX_PC_VERTEX_REUSE_BLOCK_CNTL 0x21EA
-#define A3XX_PC_PRIM_VTX_CNTL 0x21EC
-#define A3XX_PC_RESTART_INDEX 0x21ED
#define A3XX_HLSQ_CONTROL_0_REG 0x2200
#define A3XX_HLSQ_CONTROL_1_REG 0x2201
#define A3XX_HLSQ_CONTROL_2_REG 0x2202
@@ -443,11 +395,6 @@
#define A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG 0x2216
#define A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG 0x2217
#define A3XX_HLSQ_CL_WG_OFFSET_REG 0x221A
-#define A3XX_VFD_CONTROL_0 0x2240
-#define A3XX_VFD_INDEX_MIN 0x2242
-#define A3XX_VFD_INDEX_MAX 0x2243
-#define A3XX_VFD_FETCH_INSTR_0_0 0x2246
-#define A3XX_VFD_FETCH_INSTR_0_4 0x224E
#define A3XX_VFD_FETCH_INSTR_1_0 0x2247
#define A3XX_VFD_FETCH_INSTR_1_1 0x2249
#define A3XX_VFD_FETCH_INSTR_1_2 0x224B
@@ -464,10 +411,6 @@
#define A3XX_VFD_FETCH_INSTR_1_D 0x2261
#define A3XX_VFD_FETCH_INSTR_1_E 0x2263
#define A3XX_VFD_FETCH_INSTR_1_F 0x2265
-#define A3XX_VFD_DECODE_INSTR_0 0x2266
-#define A3XX_VFD_VS_THREADING_THRESHOLD 0x227E
-#define A3XX_VPC_ATTR 0x2280
-#define A3XX_VPC_VARY_CYLWRAP_ENABLE_1 0x228B
#define A3XX_SP_SP_CTRL_REG 0x22C0
#define A3XX_SP_VS_CTRL_REG0 0x22C4
#define A3XX_SP_VS_CTRL_REG1 0x22C5
@@ -510,13 +453,7 @@
#define A3XX_SP_FS_IMAGE_OUTPUT_REG_3 0x22F7
#define A3XX_SP_FS_LENGTH_REG 0x22FF
#define A3XX_PA_SC_AA_CONFIG 0x2301
-#define A3XX_TPL1_TP_VS_TEX_OFFSET 0x2340
-#define A3XX_TPL1_TP_FS_TEX_OFFSET 0x2342
-#define A3XX_TPL1_TP_FS_BORDER_COLOR_BASE_ADDR 0x2343
#define A3XX_VBIF_CLKON 0x3001
-#define A3XX_VBIF_FIXED_SORT_EN 0x300C
-#define A3XX_VBIF_FIXED_SORT_SEL0 0x300D
-#define A3XX_VBIF_FIXED_SORT_SEL1 0x300E
#define A3XX_VBIF_ABIT_SORT 0x301C
#define A3XX_VBIF_ABIT_SORT_CONF 0x301D
#define A3XX_VBIF_GATE_OFF_WRREQ_EN 0x302A
@@ -529,12 +466,8 @@
#define A3XX_VBIF_DDR_OUT_MAX_BURST 0x3036
#define A3XX_VBIF_ARB_CTL 0x303C
#define A3XX_VBIF_ROUND_ROBIN_QOS_ARB 0x3049
-#define A3XX_VBIF_OUT_AXI_AMEMTYPE_CONF0 0x3058
#define A3XX_VBIF_OUT_AXI_AOOO_EN 0x305E
#define A3XX_VBIF_OUT_AXI_AOOO 0x305F
-#define A3XX_VBIF_PERF_CNT_EN 0x3070
-#define A3XX_VBIF_PERF_CNT_CLR 0x3071
-#define A3XX_VBIF_PERF_CNT_SEL 0x3072
#define A3XX_VBIF_PERF_CNT0_LO 0x3073
#define A3XX_VBIF_PERF_CNT0_HI 0x3074
#define A3XX_VBIF_PERF_CNT1_LO 0x3075
@@ -553,14 +486,6 @@
#define A3XX_VBIF_XIN_HALT_CTRL1 0x3081
/* VBIF register offsets for A306 */
-#define A3XX_VBIF2_PERF_CNT_EN0 0x30c0
-#define A3XX_VBIF2_PERF_CNT_EN1 0x30c1
-#define A3XX_VBIF2_PERF_CNT_EN2 0x30c2
-#define A3XX_VBIF2_PERF_CNT_EN3 0x30c3
-#define A3XX_VBIF2_PERF_CNT_CLR0 0x30c8
-#define A3XX_VBIF2_PERF_CNT_CLR1 0x30c9
-#define A3XX_VBIF2_PERF_CNT_CLR2 0x30ca
-#define A3XX_VBIF2_PERF_CNT_CLR3 0x30cb
#define A3XX_VBIF2_PERF_CNT_SEL0 0x30d0
#define A3XX_VBIF2_PERF_CNT_SEL1 0x30d1
#define A3XX_VBIF2_PERF_CNT_SEL2 0x30d2
@@ -577,9 +502,6 @@
#define A3XX_VBIF2_PERF_PWR_CNT_EN0 0x3100
#define A3XX_VBIF2_PERF_PWR_CNT_EN1 0x3101
#define A3XX_VBIF2_PERF_PWR_CNT_EN2 0x3102
-#define A3XX_VBIF2_PERF_PWR_CNT_CLR0 0x3108
-#define A3XX_VBIF2_PERF_PWR_CNT_CLR1 0x3109
-#define A3XX_VBIF2_PERF_PWR_CNT_CLR2 0x310A
#define A3XX_VBIF2_PERF_PWR_CNT_LOW0 0x3110
#define A3XX_VBIF2_PERF_PWR_CNT_LOW1 0x3111
#define A3XX_VBIF2_PERF_PWR_CNT_LOW2 0x3112
@@ -590,240 +512,7 @@
#define A3XX_VBIF_DDR_OUTPUT_RECOVERABLE_HALT_CTRL0 0x3800
#define A3XX_VBIF_DDR_OUTPUT_RECOVERABLE_HALT_CTRL1 0x3801
-/* Various flags used by the context switch code */
-
-#define SP_MULTI 0
-#define SP_BUFFER_MODE 1
-#define SP_TWO_VTX_QUADS 0
-#define SP_PIXEL_BASED 0
-#define SP_R8G8B8A8_UNORM 8
-#define SP_FOUR_PIX_QUADS 1
-
-#define HLSQ_DIRECT 0
-#define HLSQ_BLOCK_ID_SP_VS 4
-#define HLSQ_SP_VS_INSTR 0
-#define HLSQ_SP_FS_INSTR 0
-#define HLSQ_BLOCK_ID_SP_FS 6
-#define HLSQ_TWO_PIX_QUADS 0
-#define HLSQ_TWO_VTX_QUADS 0
-#define HLSQ_BLOCK_ID_TP_TEX 2
-#define HLSQ_TP_TEX_SAMPLERS 0
-#define HLSQ_TP_TEX_MEMOBJ 1
-#define HLSQ_BLOCK_ID_TP_MIPMAP 3
-#define HLSQ_TP_MIPMAP_BASE 1
-#define HLSQ_FOUR_PIX_QUADS 1
-
-#define RB_FACTOR_ONE 1
-#define RB_BLEND_OP_ADD 0
-#define RB_FACTOR_ZERO 0
-#define RB_DITHER_DISABLE 0
-#define RB_DITHER_ALWAYS 1
-#define RB_FRAG_NEVER 0
-#define RB_ENDIAN_NONE 0
-#define RB_R8G8B8A8_UNORM 8
-#define RB_RESOLVE_PASS 2
-#define RB_CLEAR_MODE_RESOLVE 1
-#define RB_TILINGMODE_LINEAR 0
-#define RB_REF_NEVER 0
-#define RB_FRAG_LESS 1
-#define RB_REF_ALWAYS 7
-#define RB_STENCIL_KEEP 0
-#define RB_RENDERING_PASS 0
-#define RB_TILINGMODE_32X32 2
-
-#define PC_DRAW_TRIANGLES 2
-#define PC_DI_PT_RECTLIST 8
-#define PC_DI_SRC_SEL_AUTO_INDEX 2
-#define PC_DI_INDEX_SIZE_16_BIT 0
-#define PC_DI_IGNORE_VISIBILITY 0
-#define PC_DI_PT_TRILIST 4
-#define PC_DI_SRC_SEL_IMMEDIATE 1
-#define PC_DI_INDEX_SIZE_32_BIT 1
-
-#define UCHE_ENTIRE_CACHE 1
-#define UCHE_OP_INVALIDATE 1
-
-/*
- * The following are bit field shifts within some of the registers defined
- * above. These are used in the context switch code in conjunction with the
- * _SET macro
- */
-
-#define GRAS_CL_CLIP_CNTL_CLIP_DISABLE 16
-#define GRAS_CL_CLIP_CNTL_IJ_PERSP_CENTER 12
-#define GRAS_CL_CLIP_CNTL_PERSP_DIVISION_DISABLE 21
-#define GRAS_CL_CLIP_CNTL_VP_CLIP_CODE_IGNORE 19
-#define GRAS_CL_CLIP_CNTL_VP_XFORM_DISABLE 20
-#define GRAS_CL_CLIP_CNTL_ZFAR_CLIP_DISABLE 17
-#define GRAS_CL_VPORT_XSCALE_VPORT_XSCALE 0
-#define GRAS_CL_VPORT_YSCALE_VPORT_YSCALE 0
-#define GRAS_CL_VPORT_ZSCALE_VPORT_ZSCALE 0
-#define GRAS_SC_CONTROL_RASTER_MODE 12
-#define GRAS_SC_CONTROL_RENDER_MODE 4
-#define GRAS_SC_SCREEN_SCISSOR_BR_BR_X 0
-#define GRAS_SC_SCREEN_SCISSOR_BR_BR_Y 16
-#define GRAS_SC_WINDOW_SCISSOR_BR_BR_X 0
-#define GRAS_SC_WINDOW_SCISSOR_BR_BR_Y 16
-#define GRAS_SU_CTRLMODE_LINEHALFWIDTH 03
-#define HLSQ_CONSTFSPRESERVEDRANGEREG_ENDENTRY 16
-#define HLSQ_CONSTFSPRESERVEDRANGEREG_STARTENTRY 0
-#define HLSQ_CTRL0REG_CHUNKDISABLE 26
-#define HLSQ_CTRL0REG_CONSTSWITCHMODE 27
-#define HLSQ_CTRL0REG_FSSUPERTHREADENABLE 6
-#define HLSQ_CTRL0REG_FSTHREADSIZE 4
-#define HLSQ_CTRL0REG_LAZYUPDATEDISABLE 28
-#define HLSQ_CTRL0REG_RESERVED2 10
-#define HLSQ_CTRL0REG_SPCONSTFULLUPDATE 29
-#define HLSQ_CTRL0REG_SPSHADERRESTART 9
-#define HLSQ_CTRL0REG_TPFULLUPDATE 30
-#define HLSQ_CTRL1REG_RESERVED1 9
-#define HLSQ_CTRL1REG_VSSUPERTHREADENABLE 8
-#define HLSQ_CTRL1REG_VSTHREADSIZE 6
-#define HLSQ_CTRL2REG_PRIMALLOCTHRESHOLD 26
-#define HLSQ_FSCTRLREG_FSCONSTLENGTH 0
-#define HLSQ_FSCTRLREG_FSCONSTSTARTOFFSET 12
-#define HLSQ_FSCTRLREG_FSINSTRLENGTH 24
-#define HLSQ_VSCTRLREG_VSINSTRLENGTH 24
-#define PC_PRIM_VTX_CONTROL_POLYMODE_BACK_PTYPE 8
-#define PC_PRIM_VTX_CONTROL_POLYMODE_FRONT_PTYPE 5
-#define PC_PRIM_VTX_CONTROL_PROVOKING_VTX_LAST 25
-#define PC_PRIM_VTX_CONTROL_STRIDE_IN_VPC 0
-#define PC_DRAW_INITIATOR_PRIM_TYPE 0
-#define PC_DRAW_INITIATOR_SOURCE_SELECT 6
-#define PC_DRAW_INITIATOR_VISIBILITY_CULLING_MODE 9
-#define PC_DRAW_INITIATOR_INDEX_SIZE 0x0B
-#define PC_DRAW_INITIATOR_SMALL_INDEX 0x0D
-#define PC_DRAW_INITIATOR_PRE_DRAW_INITIATOR_ENABLE 0x0E
-#define RB_COPYCONTROL_COPY_GMEM_BASE 14
-#define RB_COPYCONTROL_RESOLVE_CLEAR_MODE 4
-#define RB_COPYDESTBASE_COPY_DEST_BASE 4
-#define RB_COPYDESTINFO_COPY_COMPONENT_ENABLE 14
-#define RB_COPYDESTINFO_COPY_DEST_ENDIAN 18
-#define RB_COPYDESTINFO_COPY_DEST_FORMAT 2
-#define RB_COPYDESTINFO_COPY_DEST_TILE 0
-#define RB_COPYDESTPITCH_COPY_DEST_PITCH 0
-#define RB_DEPTHCONTROL_Z_TEST_FUNC 4
-#define RB_MODECONTROL_RENDER_MODE 8
-#define RB_MODECONTROL_MARB_CACHE_SPLIT_MODE 15
-#define RB_MODECONTROL_PACKER_TIMER_ENABLE 16
-#define RB_MRTBLENDCONTROL_ALPHA_BLEND_OPCODE 21
-#define RB_MRTBLENDCONTROL_ALPHA_DEST_FACTOR 24
-#define RB_MRTBLENDCONTROL_ALPHA_SRC_FACTOR 16
-#define RB_MRTBLENDCONTROL_CLAMP_ENABLE 29
-#define RB_MRTBLENDCONTROL_RGB_BLEND_OPCODE 5
-#define RB_MRTBLENDCONTROL_RGB_DEST_FACTOR 8
-#define RB_MRTBLENDCONTROL_RGB_SRC_FACTOR 0
-#define RB_MRTBUFBASE_COLOR_BUF_BASE 4
-#define RB_MRTBUFINFO_COLOR_BUF_PITCH 17
-#define RB_MRTBUFINFO_COLOR_FORMAT 0
-#define RB_MRTBUFINFO_COLOR_TILE_MODE 6
-#define RB_MRTCONTROL_COMPONENT_ENABLE 24
-#define RB_MRTCONTROL_DITHER_MODE 12
-#define RB_MRTCONTROL_READ_DEST_ENABLE 3
-#define RB_MRTCONTROL_ROP_CODE 8
-#define RB_MSAACONTROL_MSAA_DISABLE 10
-#define RB_MSAACONTROL_SAMPLE_MASK 16
-#define RB_RENDERCONTROL_ALPHA_TEST_FUNC 24
-#define RB_RENDERCONTROL_BIN_WIDTH 4
-#define RB_RENDERCONTROL_DISABLE_COLOR_PIPE 12
-#define RB_STENCILCONTROL_STENCIL_FAIL 11
-#define RB_STENCILCONTROL_STENCIL_FAIL_BF 23
-#define RB_STENCILCONTROL_STENCIL_FUNC 8
-#define RB_STENCILCONTROL_STENCIL_FUNC_BF 20
-#define RB_STENCILCONTROL_STENCIL_ZFAIL 17
-#define RB_STENCILCONTROL_STENCIL_ZFAIL_BF 29
-#define RB_STENCILCONTROL_STENCIL_ZPASS 14
-#define RB_STENCILCONTROL_STENCIL_ZPASS_BF 26
-#define SP_FSCTRLREG0_FSFULLREGFOOTPRINT 10
-#define SP_FSCTRLREG0_FSHALFREGFOOTPRINT 4
-#define SP_FSCTRLREG0_FSICACHEINVALID 2
-#define SP_FSCTRLREG0_FSINOUTREGOVERLAP 18
-#define SP_FSCTRLREG0_FSINSTRBUFFERMODE 1
-#define SP_FSCTRLREG0_FSLENGTH 24
-#define SP_FSCTRLREG0_FSSUPERTHREADMODE 21
-#define SP_FSCTRLREG0_FSTHREADMODE 0
-#define SP_FSCTRLREG0_FSTHREADSIZE 20
-#define SP_FSCTRLREG0_PIXLODENABLE 22
-#define SP_FSCTRLREG1_FSCONSTLENGTH 0
-#define SP_FSCTRLREG1_FSINITIALOUTSTANDING 20
-#define SP_FSCTRLREG1_HALFPRECVAROFFSET 24
-#define SP_FSMRTREG_REGID 0
-#define SP_FSMRTREG_PRECISION 8
-#define SP_FSOUTREG_PAD0 2
-#define SP_IMAGEOUTPUTREG_MRTFORMAT 0
-#define SP_IMAGEOUTPUTREG_DEPTHOUTMODE 3
-#define SP_IMAGEOUTPUTREG_PAD0 6
-#define SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET 16
-#define SP_OBJOFFSETREG_SHADEROBJOFFSETINIC 25
-#define SP_SHADERLENGTH_LEN 0
-#define SP_SPCTRLREG_CONSTMODE 18
-#define SP_SPCTRLREG_LOMODE 22
-#define SP_SPCTRLREG_SLEEPMODE 20
-#define SP_VSCTRLREG0_VSFULLREGFOOTPRINT 10
-#define SP_VSCTRLREG0_VSICACHEINVALID 2
-#define SP_VSCTRLREG0_VSINSTRBUFFERMODE 1
-#define SP_VSCTRLREG0_VSLENGTH 24
-#define SP_VSCTRLREG0_VSSUPERTHREADMODE 21
-#define SP_VSCTRLREG0_VSTHREADMODE 0
-#define SP_VSCTRLREG0_VSTHREADSIZE 20
-#define SP_VSCTRLREG1_VSINITIALOUTSTANDING 24
-#define SP_VSOUTREG_COMPMASK0 9
-#define SP_VSPARAMREG_POSREGID 0
-#define SP_VSPARAMREG_PSIZEREGID 8
-#define SP_VSPARAMREG_TOTALVSOUTVAR 20
-#define SP_VSVPCDSTREG_OUTLOC0 0
-#define TPL1_TPTEXOFFSETREG_BASETABLEPTR 16
-#define TPL1_TPTEXOFFSETREG_MEMOBJOFFSET 8
-#define TPL1_TPTEXOFFSETREG_SAMPLEROFFSET 0
-#define UCHE_INVALIDATE1REG_OPCODE 0x1C
-#define UCHE_INVALIDATE1REG_ALLORPORTION 0x1F
-#define VFD_BASEADDR_BASEADDR 0
-#define VFD_CTRLREG0_PACKETSIZE 18
-#define VFD_CTRLREG0_STRMDECINSTRCNT 22
-#define VFD_CTRLREG0_STRMFETCHINSTRCNT 27
-#define VFD_CTRLREG0_TOTALATTRTOVS 0
-#define VFD_CTRLREG1_MAXSTORAGE 0
-#define VFD_CTRLREG1_REGID4INST 24
-#define VFD_CTRLREG1_REGID4VTX 16
-#define VFD_DECODEINSTRUCTIONS_CONSTFILL 4
-#define VFD_DECODEINSTRUCTIONS_FORMAT 6
-#define VFD_DECODEINSTRUCTIONS_LASTCOMPVALID 29
-#define VFD_DECODEINSTRUCTIONS_REGID 12
-#define VFD_DECODEINSTRUCTIONS_SHIFTCNT 24
-#define VFD_DECODEINSTRUCTIONS_SWITCHNEXT 30
-#define VFD_DECODEINSTRUCTIONS_WRITEMASK 0
-#define VFD_FETCHINSTRUCTIONS_BUFSTRIDE 7
-#define VFD_FETCHINSTRUCTIONS_FETCHSIZE 0
-#define VFD_FETCHINSTRUCTIONS_INDEXDECODE 18
-#define VFD_FETCHINSTRUCTIONS_STEPRATE 24
-#define VFD_FETCHINSTRUCTIONS_SWITCHNEXT 17
-#define VFD_THREADINGTHRESHOLD_REGID_VTXCNT 8
-#define VFD_THREADINGTHRESHOLD_REGID_THRESHOLD 0
-#define VFD_THREADINGTHRESHOLD_RESERVED6 4
-#define VPC_VPCATTR_LMSIZE 28
-#define VPC_VPCATTR_THRHDASSIGN 12
-#define VPC_VPCATTR_TOTALATTR 0
-#define VPC_VPCPACK_NUMFPNONPOSVAR 8
-#define VPC_VPCPACK_NUMNONPOSVSVAR 16
-#define VPC_VPCVARPSREPLMODE_COMPONENT08 0
-#define VPC_VPCVARPSREPLMODE_COMPONENT09 2
-#define VPC_VPCVARPSREPLMODE_COMPONENT0A 4
-#define VPC_VPCVARPSREPLMODE_COMPONENT0B 6
-#define VPC_VPCVARPSREPLMODE_COMPONENT0C 8
-#define VPC_VPCVARPSREPLMODE_COMPONENT0D 10
-#define VPC_VPCVARPSREPLMODE_COMPONENT0E 12
-#define VPC_VPCVARPSREPLMODE_COMPONENT0F 14
-#define VPC_VPCVARPSREPLMODE_COMPONENT10 16
-#define VPC_VPCVARPSREPLMODE_COMPONENT11 18
-#define VPC_VPCVARPSREPLMODE_COMPONENT12 20
-#define VPC_VPCVARPSREPLMODE_COMPONENT13 22
-#define VPC_VPCVARPSREPLMODE_COMPONENT14 24
-#define VPC_VPCVARPSREPLMODE_COMPONENT15 26
-#define VPC_VPCVARPSREPLMODE_COMPONENT16 28
-#define VPC_VPCVARPSREPLMODE_COMPONENT17 30
-
/* RBBM Debug bus block IDs */
-#define RBBM_BLOCK_ID_NONE 0x0
#define RBBM_BLOCK_ID_CP 0x1
#define RBBM_BLOCK_ID_RBBM 0x2
#define RBBM_BLOCK_ID_VBIF 0x3
@@ -871,7 +560,6 @@
/* VBIF countables */
#define VBIF_AXI_TOTAL_BEATS 85
-#define VBIF_DDR_TOTAL_CYCLES 110
/* VBIF Recoverable HALT bit value */
#define VBIF_RECOVERABLE_HALT_CTRL 0x1
diff --git a/drivers/gpu/msm/a4xx_reg.h b/drivers/gpu/msm/a4xx_reg.h
index 78db8dd2da40..4b69583a6ce1 100644
--- a/drivers/gpu/msm/a4xx_reg.h
+++ b/drivers/gpu/msm/a4xx_reg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -102,7 +102,6 @@ enum a4xx_rb_perfctr_rb_sel {
#define A4XX_RBBM_INTERFACE_HANG_INT_CTL 0x2f
#define A4XX_RBBM_INT_CLEAR_CMD 0x36
#define A4XX_RBBM_INT_0_MASK 0x37
-#define A4XX_RBBM_ALWAYSON_COUNTER_CNTL 0x3d
#define A4XX_RBBM_RBBM_CTL 0x3e
#define A4XX_RBBM_CLOCK_CTL2 0x42
#define A4XX_RBBM_BLOCK_SW_RESET_CMD 0x45
@@ -113,13 +112,8 @@ enum a4xx_rb_perfctr_rb_sel {
#define A4XX_RBBM_CFG_DEBBUS_SEL_D 0x4d
#define A4XX_RBBM_CFG_DEBBUS_SEL_PING_INDEX_SHIFT 0
#define A4XX_RBBM_CFG_DEBBUS_SEL_PING_BLK_SEL_SHIFT 8
-#define A4XX_RBBM_CFG_DEBBUS_SEL_PONG_INDEX_SHIFT 16
-#define A4XX_RBBM_CFG_DEBBUS_SEL_PONG_BLK_SEL_SHIFT 24
#define A4XX_RBBM_CFG_DEBBUS_CTLT 0x4e
-#define A4XX_RBBM_CFG_DEBBUS_CTLT_ENT_SHIFT 0
-#define A4XX_RBBM_CFG_DEBBUS_CTLT_GRANU_SHIFT 12
-#define A4XX_RBBM_CFG_DEBBUS_CTLT_SEGT_SHIFT 28
#define A4XX_RBBM_CFG_DEBBUS_CTLM 0x4f
#define A4XX_RBBM_CFG_DEBBUS_CTLT_ENABLE_SHIFT 24
@@ -138,24 +132,7 @@ enum a4xx_rb_perfctr_rb_sel {
#define A4XX_RBBM_CFG_DEBBUS_BYTEL_0 0x5a
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_0_BYTEL0_SHIFT 0
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_0_BYTEL1_SHIFT 4
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_0_BYTEL2_SHIFT 8
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_0_BYTEL3_SHIFT 12
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_0_BYTEL4_SHIFT 16
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_0_BYTEL5_SHIFT 20
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_0_BYTEL6_SHIFT 24
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_0_BYTEL7_SHIFT 28
-
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_1 0x5b
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_1_BYTEL8_SHIFT 0
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_1_BYTEL9_SHIFT 4
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_1_BYTEL10_SHIFT 8
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_1_BYTEL11_SHIFT 12
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_1_BYTEL12_SHIFT 16
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_1_BYTEL13_SHIFT 20
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_1_BYTEL14_SHIFT 24
-#define A4XX_RBBM_CFG_DEBBUS_BYTEL_1_BYTEL15_SHIFT 28
+#define A4XX_RBBM_CFG_DEBBUS_BYTEL_1 0x5b
#define A4XX_RBBM_CFG_DEBBUS_IVTE_0 0x5c
#define A4XX_RBBM_CFG_DEBBUS_IVTE_1 0x5d
@@ -425,14 +402,7 @@ enum a4xx_rb_perfctr_rb_sel {
#define A4XX_RBBM_AHB_PFP_SPLIT_STATUS 0x18d
#define A4XX_RBBM_AHB_ERROR_STATUS 0x18f
#define A4XX_RBBM_STATUS 0x191
-#define A4XX_RBBM_CFG_COUNTER0 0x1a2
-#define A4XX_RBBM_CFG_DEBBUS_TRACE_BUF0 0x1a9
-#define A4XX_RBBM_CFG_DEBBUS_TRACE_BUF1 0x1aa
-#define A4XX_RBBM_CFG_DEBBUS_TRACE_BUF2 0x1ab
-#define A4XX_RBBM_CFG_DEBBUS_TRACE_BUF3 0x1ac
#define A4XX_RBBM_CFG_DEBBUS_TRACE_BUF4 0x1ad
-#define A4XX_RBBM_CFG_DEBBUS_MISR0 0x1ae
-#define A4XX_RBBM_CFG_DEBBUS_MISR1 0x1af
#define A4XX_RBBM_POWER_STATUS 0x1b0
#define A4XX_RBBM_PPD_V2_SP_PWR_WEIGHTS 0x1b2
#define A4XX_RBBM_PPD_V2_SP_RB_EPOCH_TH 0x1b3
@@ -440,8 +410,6 @@ enum a4xx_rb_perfctr_rb_sel {
#define A4XX_RBBM_PPD_RAMP_V2_CONTROL 0x1b5
#define A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL2 0x1b8
#define A4XX_RBBM_PPD_CTRL 0x1b9
-#define A4XX_RBBM_PPD_EPOCH_INTRA_TH_1 0x1ba
-#define A4XX_RBBM_PPD_EPOCH_INTRA_TH_2 0x1bb
#define A4XX_RBBM_PPD_EPOCH_INTER_TH_HIGH_CLEAR_THR 0x1bc
#define A4XX_RBBM_PPD_EPOCH_INTER_TH_LOW 0x1bd
/* SECVID registers */
@@ -473,13 +441,8 @@ enum a4xx_rb_perfctr_rb_sel {
#define A4XX_CP_ME_RAM_WADDR 0x225
#define A4XX_CP_ME_RAM_RADDR 0x226
#define A4XX_CP_ME_RAM_DATA 0x227
-#define A4XX_CP_SCRATCH_UMASK 0x228
-#define A4XX_CP_SCRATCH_ADDR 0x229
#define A4XX_CP_PREEMPT 0x22a
-/* PREEMPT register bit shifts */
-#define A4XX_CP_PREEMPT_STOP_SHIFT 0
-#define A4XX_CP_PREEMPT_RESUME_SHIFT 1
#define A4XX_CP_PREEMPT_DISABLE 0x22b
#define A4XX_CP_CNTL 0x22c
@@ -513,7 +476,6 @@ enum a4xx_rb_perfctr_rb_sel {
#define A4XX_CP_PERFCTR_CP_SEL_6 0x506
#define A4XX_CP_PERFCTR_CP_SEL_7 0x507
-#define A4XX_CP_SCRATCH_REG0 0x578
#define A4XX_CP_SCRATCH_REG6 0x57e
#define A4XX_CP_SCRATCH_REG7 0x57f
#define A4XX_CP_SCRATCH_REG8 0x580
@@ -540,9 +502,6 @@ enum a4xx_rb_perfctr_rb_sel {
#define A4XX_SP_CS_CTRL_0 0x2300
#define A4XX_SP_CS_OBJ_OFFSET 0x2301
#define A4XX_SP_CS_OBJ_START 0x2302
-#define A4XX_SP_CS_PVT_MEM_PARAM 0x2303
-#define A4XX_SP_CS_PVT_MEM_ADDR 0x2304
-#define A4XX_SP_CS_PVT_MEM_SIZE 0x2305
#define A4XX_SP_CS_LENGTH 0x2306
#define A4XX_SP_MODE_CONTROL 0xec3
#define A4XX_SP_PERFCTR_SP_SEL_0 0xec4
@@ -611,8 +570,6 @@ enum a4xx_sp_perfctr_sp_sel {
#define A4XX_VSC_PERFCTR_VSC_SEL_1 0xc51
/* VFD registers */
-#define A4XX_VFD_CONTROL_0 0x2200
-#define A4XX_VFD_FETCH_INSTR_0_0 0x220a
#define A4XX_VFD_FETCH_INSTR_1_31 0x2287
#define A4XX_VFD_PERFCTR_VFD_SEL_0 0xe43
#define A4XX_VFD_PERFCTR_VFD_SEL_1 0xe44
@@ -699,14 +656,6 @@ enum a4xx_vfd_perfctr_vfd_sel {
#define A4XX_VBIF_TEST_BUS_OUT 0x308c
-#define A4XX_VBIF_PERF_CNT_EN0 0x30c0
-#define A4XX_VBIF_PERF_CNT_EN1 0x30c1
-#define A4XX_VBIF_PERF_CNT_EN2 0x30c2
-#define A4XX_VBIF_PERF_CNT_EN3 0x30c3
-#define A4XX_VBIF_PERF_CNT_CLR0 0x30c8
-#define A4XX_VBIF_PERF_CNT_CLR1 0x30c9
-#define A4XX_VBIF_PERF_CNT_CLR2 0x30ca
-#define A4XX_VBIF_PERF_CNT_CLR3 0x30cb
#define A4XX_VBIF_PERF_CNT_SEL0 0x30d0
#define A4XX_VBIF_PERF_CNT_SEL1 0x30d1
#define A4XX_VBIF_PERF_CNT_SEL2 0x30d2
@@ -724,10 +673,6 @@ enum a4xx_vfd_perfctr_vfd_sel {
#define A4XX_VBIF_PERF_PWR_CNT_EN1 0x3101
#define A4XX_VBIF_PERF_PWR_CNT_EN2 0x3102
#define A4XX_VBIF_PERF_PWR_CNT_EN3 0x3103
-#define A4XX_VBIF_PERF_PWR_CNT_CLR0 0x3108
-#define A4XX_VBIF_PERF_PWR_CNT_CLR1 0x3109
-#define A4XX_VBIF_PERF_PWR_CNT_CLR2 0x310A
-#define A4XX_VBIF_PERF_PWR_CNT_CLR3 0x310B
#define A4XX_VBIF_PERF_PWR_CNT_LOW0 0x3110
#define A4XX_VBIF_PERF_PWR_CNT_LOW1 0x3111
#define A4XX_VBIF_PERF_PWR_CNT_LOW2 0x3112
@@ -737,12 +682,6 @@ enum a4xx_vfd_perfctr_vfd_sel {
#define A4XX_VBIF_PERF_PWR_CNT_HIGH2 0x311a
#define A4XX_VBIF_PERF_PWR_CNT_HIGH3 0x311b
-/* Bit flags for RBBM_CTL */
-#define A4XX_RBBM_RBBM_CTL_RESET_PWR_CTR0 0x00000001
-#define A4XX_RBBM_RBBM_CTL_RESET_PWR_CTR1 0x00000002
-#define A4XX_RBBM_RBBM_CTL_ENABLE_PWR_CTR0 0x00000010
-#define A4XX_RBBM_RBBM_CTL_ENABLE_PWR_CTR1 0x00000020
-
/* GRAS registers */
#define A4XX_GRAS_PERFCTR_TSE_SEL_0 0xc88
#define A4XX_GRAS_PERFCTR_TSE_SEL_1 0xc89
@@ -772,7 +711,6 @@ enum a4xx_pc_perfctr_pc_sel {
/* HLSQ registers */
#define A4XX_HLSQ_TIMEOUT_THRESHOLD 0xe00
-#define A4XX_HLSQ_STATE_RESTORE_TRIGGER 0xe01
#define A4XX_HLSQ_MODE_CONTROL 0xe05
#define A4XX_HLSQ_PERFCTR_HLSQ_SEL_0 0xe06
#define A4XX_HLSQ_PERFCTR_HLSQ_SEL_1 0xe07
@@ -784,24 +722,11 @@ enum a4xx_pc_perfctr_pc_sel {
#define A4XX_HLSQ_PERFCTR_HLSQ_SEL_7 0xe0d
#define A4XX_HLSQ_SPTP_RDSEL 0xe30
#define A4xx_HLSQ_CONTROL_0 0x23c0
-#define A4xx_HLSQ_CONTROL_1 0x23c1
-#define A4xx_HLSQ_CONTROL_2 0x23c2
-#define A4xx_HLSQ_CONTROL_3 0x23c3
-#define A4xx_HLSQ_CONTROL_4 0x23c4
#define A4XX_HLSQ_CS_CONTROL 0x23ca
#define A4XX_HLSQ_CL_NDRANGE_0 0x23cd
-#define A4XX_HLSQ_CL_NDRANGE_1 0x23ce
-#define A4XX_HLSQ_CL_NDRANGE_2 0x23cf
-#define A4XX_HLSQ_CL_NDRANGE_3 0x23d0
-#define A4XX_HLSQ_CL_NDRANGE_4 0x23d1
-#define A4XX_HLSQ_CL_NDRANGE_5 0x23d2
-#define A4XX_HLSQ_CL_NDRANGE_6 0x23d3
#define A4XX_HLSQ_CL_CONTROL_0 0x23d4
-#define A4XX_HLSQ_CL_CONTROL_1 0x23d5
#define A4XX_HLSQ_CL_KERNEL_CONST 0x23d6
#define A4XX_HLSQ_CL_KERNEL_GROUP_X 0x23d7
-#define A4XX_HLSQ_CL_KERNEL_GROUP_Y 0x23d8
-#define A4XX_HLSQ_CL_KERNEL_GROUP_Z 0x23d9
#define A4XX_HLSQ_CL_WG_OFFSET 0x23da
#define A4XX_HLSQ_UPDATE_CONTROL 0x23db
@@ -863,9 +788,6 @@ enum a4xx_uche_perfctr_uche_sel {
#define A4XX_TPL1_PERFCTR_TP_SEL_6 0xf0a
#define A4XX_TPL1_PERFCTR_TP_SEL_7 0xf0b
#define A4XX_TPL1_TP_TEX_TSIZE_1 0x23a0
-#define A4XX_TPL1_TP_CS_BORDER_COLOR_BASE_ADDR 0x23A4
-#define A4XX_TPL1_TP_CS_SAMPLER_BASE_ADDR 0x23A5
-#define A4XX_TPL1_TP_CS_TEXMEMOBJ_BASE_ADDR 0x23A6
enum a4xx_tpl1_perfctr_tp_sel {
TP_OUTPUT_TEXELS_POINT = 0x2,
diff --git a/drivers/gpu/msm/a5xx_reg.h b/drivers/gpu/msm/a5xx_reg.h
index da5412c309ad..372bfad48a09 100644
--- a/drivers/gpu/msm/a5xx_reg.h
+++ b/drivers/gpu/msm/a5xx_reg.h
@@ -131,9 +131,6 @@
#define A5XX_CP_POWERCTR_CP_SEL_2 0xBBC
#define A5XX_CP_POWERCTR_CP_SEL_3 0xBBD
-/* CP_EVENT_WRITE events */
-#define A5XX_CACHE_FLUSH_TS 0x4
-
/* RBBM registers */
#define A5XX_RBBM_CFG_DBGBUS_SEL_A 0x4
#define A5XX_RBBM_CFG_DBGBUS_SEL_B 0x5
@@ -141,8 +138,6 @@
#define A5XX_RBBM_CFG_DBGBUS_SEL_D 0x7
#define A5XX_RBBM_CFG_DBGBUS_SEL_PING_INDEX_SHIFT 0x0
#define A5XX_RBBM_CFG_DBGBUS_SEL_PING_BLK_SEL_SHIFT 0x8
-#define A5XX_RBBM_CFG_DBGBUS_SEL_PONG_INDEX_SHIFT 0x10
-#define A5XX_RBBM_CFG_DBGBUS_SEL_PONG_BLK_SEL_SHIFT 0x18
#define A5XX_RBBM_CFG_DBGBUS_CNTLT 0x8
#define A5XX_RBBM_CFG_DBGBUS_CNTLM 0x9
@@ -536,10 +531,6 @@
#define A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI 0xF801
#define A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE 0xF802
#define A5XX_RBBM_SECVID_TSB_CNTL 0xF803
-#define A5XX_RBBM_SECVID_TSB_COMP_STATUS_LO 0xF804
-#define A5XX_RBBM_SECVID_TSB_COMP_STATUS_HI 0xF805
-#define A5XX_RBBM_SECVID_TSB_UCHE_STATUS_LO 0xF806
-#define A5XX_RBBM_SECVID_TSB_UCHE_STATUS_HI 0xF807
#define A5XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL 0xF810
/* VSC registers */
@@ -614,7 +605,6 @@
#define A5XX_PC_PERFCTR_PC_SEL_7 0xD17
/* HLSQ registers */
-#define A5XX_HLSQ_TIMEOUT_THRESHOLD 0xE00
#define A5XX_HLSQ_ADDR_MODE_CNTL 0xE05
#define A5XX_HLSQ_PERFCTR_HLSQ_SEL_0 0xE10
#define A5XX_HLSQ_PERFCTR_HLSQ_SEL_1 0xE11
@@ -624,7 +614,6 @@
#define A5XX_HLSQ_PERFCTR_HLSQ_SEL_5 0xE15
#define A5XX_HLSQ_PERFCTR_HLSQ_SEL_6 0xE16
#define A5XX_HLSQ_PERFCTR_HLSQ_SEL_7 0xE17
-#define A5XX_HLSQ_SPTP_RDSEL 0xF08
#define A5XX_HLSQ_DBG_READ_SEL 0xBC00
#define A5XX_HLSQ_DBG_AHB_READ_APERTURE 0xA000
@@ -648,7 +637,6 @@
/* UCHE registers */
#define A5XX_UCHE_ADDR_MODE_CNTL 0xE80
-#define A5XX_UCHE_SVM_CNTL 0xE82
#define A5XX_UCHE_WRITE_THRU_BASE_LO 0xE87
#define A5XX_UCHE_WRITE_THRU_BASE_HI 0xE88
#define A5XX_UCHE_TRAP_BASE_LO 0xE89
@@ -721,12 +709,8 @@
#define A5XX_VBIF_CLKON_FORCE_ON_TESTBUS_MASK 0x1
#define A5XX_VBIF_CLKON_FORCE_ON_TESTBUS_SHIFT 0x1
-#define A5XX_VBIF_ABIT_SORT 0x3028
-#define A5XX_VBIF_ABIT_SORT_CONF 0x3029
#define A5XX_VBIF_ROUND_ROBIN_QOS_ARB 0x3049
#define A5XX_VBIF_GATE_OFF_WRREQ_EN 0x302A
-#define A5XX_VBIF_IN_RD_LIM_CONF0 0x302C
-#define A5XX_VBIF_IN_RD_LIM_CONF1 0x302D
#define A5XX_VBIF_XIN_HALT_CTRL0 0x3080
#define A5XX_VBIF_XIN_HALT_CTRL0_MASK 0xF
@@ -877,9 +861,7 @@
#define A5XX_GPMU_TEMP_SENSOR_ID 0xAC00
#define A5XX_GPMU_TEMP_SENSOR_CONFIG 0xAC01
-#define A5XX_GPMU_TEMP_VAL 0xAC02
#define A5XX_GPMU_DELTA_TEMP_THRESHOLD 0xAC03
-#define A5XX_GPMU_TEMP_THRESHOLD_INTR_STATUS 0xAC05
#define A5XX_GPMU_TEMP_THRESHOLD_INTR_EN_MASK 0xAC06
#define A5XX_GPMU_LEAKAGE_TEMP_COEFF_0_1 0xAC40
@@ -894,9 +876,9 @@
#define A5XX_GPMU_GPMU_PWR_THRESHOLD 0xAC80
#define A5XX_GPMU_GPMU_LLM_GLM_SLEEP_CTRL 0xACC4
#define A5XX_GPMU_GPMU_LLM_GLM_SLEEP_STATUS 0xACC5
+#define A5XX_GPMU_GPMU_ISENSE_CTRL 0xACD0
#define A5XX_GDPM_CONFIG1 0xB80C
-#define A5XX_GDPM_CONFIG2 0xB80D
#define A5XX_GDPM_INT_EN 0xB80F
#define A5XX_GDPM_INT_MASK 0xB811
#define A5XX_GPMU_BEC_ENABLE 0xB9A0
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 24c5186340e5..fa981cf575a6 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2437,13 +2437,6 @@ int adreno_rb_readtimestamp(struct adreno_device *adreno_dev,
int status = 0;
struct adreno_ringbuffer *rb = priv;
- /*
- * If user passed in a NULL pointer for timestamp, return without
- * doing anything.
- */
- if (!timestamp)
- return status;
-
if (KGSL_TIMESTAMP_QUEUED == type)
*timestamp = rb->timestamp;
else
@@ -2474,19 +2467,12 @@ static int adreno_readtimestamp(struct kgsl_device *device,
{
int status = 0;
struct kgsl_context *context = priv;
- unsigned int id = KGSL_CONTEXT_ID(context);
- BUG_ON(NULL == context || id >= KGSL_MEMSTORE_MAX);
- /*
- * If user passed in a NULL pointer for timestamp, return without
- * doing anything.
- */
- if (!timestamp)
- return status;
+ if (type == KGSL_TIMESTAMP_QUEUED) {
+ struct adreno_context *ctxt = ADRENO_CONTEXT(context);
- if (KGSL_TIMESTAMP_QUEUED == type)
- *timestamp = adreno_context_timestamp(context);
- else
+ *timestamp = ctxt->timestamp;
+ } else
status = __adreno_readtimestamp(ADRENO_DEVICE(device),
context->id, type, timestamp);
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 816185e9aad4..b8029178f932 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -55,9 +55,6 @@
/* ADRENO_GPUREV - Return the GPU ID for the given adreno_device */
#define ADRENO_GPUREV(_a) ((_a)->gpucore->gpurev)
-/* ADRENO_GPUREV - Return the GPU patchid for the given adreno_device */
-#define ADRENO_PATCHID(_a) ((_a)->gpucore->patchid)
-
/*
* ADRENO_FEATURE - return true if the specified feature is supported by the GPU
* core
@@ -132,7 +129,6 @@
#define KGSL_CMD_FLAGS_WFI BIT(2)
#define KGSL_CMD_FLAGS_PROFILE BIT(3)
#define KGSL_CMD_FLAGS_PWRON_FIXUP BIT(4)
-#define KGSL_CMD_FLAGS_MEMLIST BIT(5)
/* Command identifiers */
#define KGSL_CONTEXT_TO_MEM_IDENTIFIER 0x2EADBEEF
@@ -140,16 +136,10 @@
#define KGSL_CMD_INTERNAL_IDENTIFIER 0x2EEDD00D
#define KGSL_START_OF_IB_IDENTIFIER 0x2EADEABE
#define KGSL_END_OF_IB_IDENTIFIER 0x2ABEDEAD
-#define KGSL_END_OF_FRAME_IDENTIFIER 0x2E0F2E0F
-#define KGSL_NOP_IB_IDENTIFIER 0x20F20F20
#define KGSL_START_OF_PROFILE_IDENTIFIER 0x2DEFADE1
#define KGSL_END_OF_PROFILE_IDENTIFIER 0x2DEFADE2
#define KGSL_PWRON_FIXUP_IDENTIFIER 0x2AFAFAFA
-#define ADRENO_ISTORE_START 0x5000 /* Istore offset */
-
-#define ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW 50
-
/* One cannot wait forever for the core to idle, so set an upper limit to the
* amount of time to wait for the core to go idle
*/
@@ -734,11 +724,6 @@ struct adreno_gpudev {
void (*pre_reset)(struct adreno_device *);
};
-struct log_field {
- bool show;
- const char *display;
-};
-
/**
* enum kgsl_ft_policy_bits - KGSL fault tolerance policy bits
* @KGSL_FT_OFF: Disable fault detection (not used)
@@ -983,18 +968,6 @@ static inline int adreno_is_a540v1(struct adreno_device *adreno_dev)
return (ADRENO_GPUREV(adreno_dev) == ADRENO_REV_A540) &&
(ADRENO_CHIPID_PATCH(adreno_dev->chipid) == 0);
}
-/**
- * adreno_context_timestamp() - Return the last queued timestamp for the context
- * @k_ctxt: Pointer to the KGSL context to query
- *
- * Return the last queued context for the given context. This is used to verify
- * that incoming requests are not using an invalid (unsubmitted) timestamp
- */
-static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt)
-{
- struct adreno_context *drawctxt = ADRENO_CONTEXT(k_ctxt);
- return drawctxt->timestamp;
-}
/*
* adreno_checkreg_off() - Checks the validity of a register enum
diff --git a/drivers/gpu/msm/adreno_a3xx.h b/drivers/gpu/msm/adreno_a3xx.h
index 4ab1236020e8..11596b8bf7aa 100644
--- a/drivers/gpu/msm/adreno_a3xx.h
+++ b/drivers/gpu/msm/adreno_a3xx.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,34 @@
#ifndef __A3XX_H
#define __A3XX_H
+#include "a3xx_reg.h"
+
+#define A3XX_IRQ_FLAGS \
+ { BIT(A3XX_INT_RBBM_GPU_IDLE), "RBBM_GPU_IDLE" }, \
+ { BIT(A3XX_INT_RBBM_AHB_ERROR), "RBBM_AHB_ERR" }, \
+ { BIT(A3XX_INT_RBBM_REG_TIMEOUT), "RBBM_REG_TIMEOUT" }, \
+ { BIT(A3XX_INT_RBBM_ME_MS_TIMEOUT), "RBBM_ME_MS_TIMEOUT" }, \
+ { BIT(A3XX_INT_RBBM_PFP_MS_TIMEOUT), "RBBM_PFP_MS_TIMEOUT" }, \
+ { BIT(A3XX_INT_RBBM_ATB_BUS_OVERFLOW), "RBBM_ATB_BUS_OVERFLOW" }, \
+ { BIT(A3XX_INT_VFD_ERROR), "RBBM_VFD_ERROR" }, \
+ { BIT(A3XX_INT_CP_SW_INT), "CP_SW" }, \
+ { BIT(A3XX_INT_CP_T0_PACKET_IN_IB), "CP_T0_PACKET_IN_IB" }, \
+ { BIT(A3XX_INT_CP_OPCODE_ERROR), "CP_OPCODE_ERROR" }, \
+ { BIT(A3XX_INT_CP_RESERVED_BIT_ERROR), "CP_RESERVED_BIT_ERROR" }, \
+ { BIT(A3XX_INT_CP_HW_FAULT), "CP_HW_FAULT" }, \
+ { BIT(A3XX_INT_CP_DMA), "CP_DMA" }, \
+ { BIT(A3XX_INT_CP_IB2_INT), "CP_IB2_INT" }, \
+ { BIT(A3XX_INT_CP_IB1_INT), "CP_IB1_INT" }, \
+ { BIT(A3XX_INT_CP_RB_INT), "CP_RB_INT" }, \
+ { BIT(A3XX_INT_CP_REG_PROTECT_FAULT), "CP_REG_PROTECT_FAULT" }, \
+ { BIT(A3XX_INT_CP_RB_DONE_TS), "CP_RB_DONE_TS" }, \
+ { BIT(A3XX_INT_CP_VS_DONE_TS), "CP_VS_DONE_TS" }, \
+ { BIT(A3XX_INT_CP_PS_DONE_TS), "CP_PS_DONE_TS" }, \
+ { BIT(A3XX_INT_CACHE_FLUSH_TS), "CACHE_FLUSH_TS" }, \
+ { BIT(A3XX_INT_CP_AHB_ERROR_HALT), "CP_AHB_ERROR_HALT" }, \
+ { BIT(A3XX_INT_MISC_HANG_DETECT), "MISC_HANG_DETECT" }, \
+ { BIT(A3XX_INT_UCHE_OOB_ACCESS), "UCHE_OOB_ACCESS" }
+
unsigned int a3xx_irq_pending(struct adreno_device *adreno_dev);
int a3xx_microcode_read(struct adreno_device *adreno_dev);
diff --git a/drivers/gpu/msm/adreno_a4xx.h b/drivers/gpu/msm/adreno_a4xx.h
index 93e54e82a48c..e425dc8e9f7b 100644
--- a/drivers/gpu/msm/adreno_a4xx.h
+++ b/drivers/gpu/msm/adreno_a4xx.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,39 @@
#ifndef _ADRENO_A4XX_H_
#define _ADRENO_A4XX_H_
+#include "a4xx_reg.h"
+
+#define A4XX_IRQ_FLAGS \
+ { BIT(A4XX_INT_RBBM_GPU_IDLE), "RBBM_GPU_IDLE" }, \
+ { BIT(A4XX_INT_RBBM_REG_TIMEOUT), "RBBM_REG_TIMEOUT" }, \
+ { BIT(A4XX_INT_RBBM_ME_MS_TIMEOUT), "RBBM_ME_MS_TIMEOUT" }, \
+ { BIT(A4XX_INT_RBBM_PFP_MS_TIMEOUT), "RBBM_PFP_MS_TIMEOUT" }, \
+ { BIT(A4XX_INT_RBBM_ETS_MS_TIMEOUT), "RBBM_ETS_MS_TIMEOUT" }, \
+ { BIT(A4XX_INT_RBBM_ASYNC_OVERFLOW), "RBBM_ASYNC_OVERFLOW" }, \
+ { BIT(A4XX_INT_RBBM_GPC_ERR), "RBBM_GPC_ERR" }, \
+ { BIT(A4XX_INT_CP_SW), "CP_SW" }, \
+ { BIT(A4XX_INT_CP_OPCODE_ERROR), "CP_OPCODE_ERROR" }, \
+ { BIT(A4XX_INT_CP_RESERVED_BIT_ERROR), "CP_RESERVED_BIT_ERROR" }, \
+ { BIT(A4XX_INT_CP_HW_FAULT), "CP_HW_FAULT" }, \
+ { BIT(A4XX_INT_CP_DMA), "CP_DMA" }, \
+ { BIT(A4XX_INT_CP_IB2_INT), "CP_IB2_INT" }, \
+ { BIT(A4XX_INT_CP_IB1_INT), "CP_IB1_INT" }, \
+ { BIT(A4XX_INT_CP_RB_INT), "CP_RB_INT" }, \
+ { BIT(A4XX_INT_CP_REG_PROTECT_FAULT), "CP_REG_PROTECT_FAULT" }, \
+ { BIT(A4XX_INT_CP_RB_DONE_TS), "CP_RB_DONE_TS" }, \
+ { BIT(A4XX_INT_CP_VS_DONE_TS), "CP_VS_DONE_TS" }, \
+ { BIT(A4XX_INT_CP_PS_DONE_TS), "CP_PS_DONE_TS" }, \
+ { BIT(A4XX_INT_CACHE_FLUSH_TS), "CACHE_FLUSH_TS" }, \
+ { BIT(A4XX_INT_CP_AHB_ERROR_HALT), "CP_AHB_ERROR_HALT" }, \
+ { BIT(A4XX_INT_RBBM_ATB_BUS_OVERFLOW), "RBBM_ATB_BUS_OVERFLOW" }, \
+ { BIT(A4XX_INT_MISC_HANG_DETECT), "MISC_HANG_DETECT" }, \
+ { BIT(A4XX_INT_UCHE_OOB_ACCESS), "UCHE_OOB_ACCESS" }, \
+ { BIT(A4XX_INT_RBBM_DPM_CALC_ERR), "RBBM_DPM_CALC_ERR" }, \
+ { BIT(A4XX_INT_RBBM_DPM_EPOCH_ERR), "RBBM_DPM_CALC_ERR" }, \
+ { BIT(A4XX_INT_RBBM_DPM_THERMAL_YELLOW_ERR), \
+ "RBBM_DPM_THERMAL_YELLOW_ERR" }, \
+ { BIT(A4XX_INT_RBBM_DPM_THERMAL_RED_ERR), "RBBM_DPM_THERMAL_RED_ERR" }
+
void a4xx_snapshot(struct adreno_device *adreno_dev,
struct kgsl_snapshot *snapshot);
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index f1fc3bdede00..e173dc594789 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -1713,6 +1713,9 @@ static int isense_enable(struct adreno_device *adreno_dev)
unsigned int r;
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
+ kgsl_regrmw(device, A5XX_GPMU_GPMU_ISENSE_CTRL, 0,
+ ISENSE_CGC_EN_DISABLE);
+
kgsl_regwrite(device, A5XX_GPU_CS_ENABLE_REG,
adreno_is_a540v1(adreno_dev) ? 7 : 6);
udelay(2);
diff --git a/drivers/gpu/msm/adreno_a5xx.h b/drivers/gpu/msm/adreno_a5xx.h
index e41b5b9cce0c..e4b099aa30d1 100644
--- a/drivers/gpu/msm/adreno_a5xx.h
+++ b/drivers/gpu/msm/adreno_a5xx.h
@@ -14,6 +14,42 @@
#ifndef _ADRENO_A5XX_H_
#define _ADRENO_A5XX_H_
+#include "a5xx_reg.h"
+
+#define A5XX_IRQ_FLAGS \
+ { BIT(A5XX_INT_RBBM_GPU_IDLE), "RBBM_GPU_IDLE" }, \
+ { BIT(A5XX_INT_RBBM_AHB_ERROR), "RBBM_AHB_ERR" }, \
+ { BIT(A5XX_INT_RBBM_TRANSFER_TIMEOUT), "RBBM_TRANSFER_TIMEOUT" }, \
+ { BIT(A5XX_INT_RBBM_ME_MS_TIMEOUT), "RBBM_ME_MS_TIMEOUT" }, \
+ { BIT(A5XX_INT_RBBM_PFP_MS_TIMEOUT), "RBBM_PFP_MS_TIMEOUT" }, \
+ { BIT(A5XX_INT_RBBM_ETS_MS_TIMEOUT), "RBBM_ETS_MS_TIMEOUT" }, \
+ { BIT(A5XX_INT_RBBM_ATB_ASYNC_OVERFLOW), "RBBM_ATB_ASYNC_OVERFLOW" }, \
+ { BIT(A5XX_INT_RBBM_GPC_ERROR), "RBBM_GPC_ERR" }, \
+ { BIT(A5XX_INT_CP_SW), "CP_SW" }, \
+ { BIT(A5XX_INT_CP_HW_ERROR), "CP_OPCODE_ERROR" }, \
+ { BIT(A5XX_INT_CP_CCU_FLUSH_DEPTH_TS), "CP_CCU_FLUSH_DEPTH_TS" }, \
+ { BIT(A5XX_INT_CP_CCU_FLUSH_COLOR_TS), "CP_CCU_FLUSH_COLOR_TS" }, \
+ { BIT(A5XX_INT_CP_CCU_RESOLVE_TS), "CP_CCU_RESOLVE_TS" }, \
+ { BIT(A5XX_INT_CP_IB2), "CP_IB2_INT" }, \
+ { BIT(A5XX_INT_CP_IB1), "CP_IB1_INT" }, \
+ { BIT(A5XX_INT_CP_RB), "CP_RB_INT" }, \
+ { BIT(A5XX_INT_CP_UNUSED_1), "CP_UNUSED_1" }, \
+ { BIT(A5XX_INT_CP_RB_DONE_TS), "CP_RB_DONE_TS" }, \
+ { BIT(A5XX_INT_CP_WT_DONE_TS), "CP_WT_DONE_TS" }, \
+ { BIT(A5XX_INT_UNKNOWN_1), "UNKNOWN_1" }, \
+ { BIT(A5XX_INT_CP_CACHE_FLUSH_TS), "CP_CACHE_FLUSH_TS" }, \
+ { BIT(A5XX_INT_UNUSED_2), "UNUSED_2" }, \
+ { BIT(A5XX_INT_RBBM_ATB_BUS_OVERFLOW), "RBBM_ATB_BUS_OVERFLOW" }, \
+ { BIT(A5XX_INT_MISC_HANG_DETECT), "MISC_HANG_DETECT" }, \
+ { BIT(A5XX_INT_UCHE_OOB_ACCESS), "UCHE_OOB_ACCESS" }, \
+ { BIT(A5XX_INT_UCHE_TRAP_INTR), "UCHE_TRAP_INTR" }, \
+ { BIT(A5XX_INT_DEBBUS_INTR_0), "DEBBUS_INTR_0" }, \
+ { BIT(A5XX_INT_DEBBUS_INTR_1), "DEBBUS_INTR_1" }, \
+ { BIT(A5XX_INT_GPMU_VOLTAGE_DROOP), "GPMU_VOLTAGE_DROOP" }, \
+ { BIT(A5XX_INT_GPMU_FIRMWARE), "GPMU_FIRMWARE" }, \
+ { BIT(A5XX_INT_ISDB_CPU_IRQ), "ISDB_CPU_IRQ" }, \
+ { BIT(A5XX_INT_ISDB_UNDER_DEBUG), "ISDB_UNDER_DEBUG" }
+
#define A5XX_CP_CTXRECORD_MAGIC_REF 0x27C4BAFCUL
/* Size of each CP preemption record */
#define A5XX_CP_CTXRECORD_SIZE_IN_BYTES 0x100000
@@ -97,16 +133,19 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on);
/* A5XX_GPMU_GPMU_LLM_GLM_SLEEP_CTRL */
#define STATE_OF_CHILD GENMASK(5, 4)
#define STATE_OF_CHILD_01 BIT(4)
+#define STATE_OF_CHILD_11 (BIT(4) | BIT(5))
#define IDLE_FULL_LM_SLEEP BIT(0)
/* A5XX_GPMU_GPMU_LLM_GLM_SLEEP_STATUS */
#define WAKEUP_ACK BIT(1)
#define IDLE_FULL_ACK BIT(0)
+/* A5XX_GPMU_GPMU_ISENSE_CTRL */
+#define ISENSE_CGC_EN_DISABLE BIT(0)
+
/* A5XX_GPMU_TEMP_SENSOR_CONFIG */
#define GPMU_BCL_ENABLED BIT(4)
#define GPMU_LLM_ENABLED BIT(9)
-#define GPMU_LMH_ENABLED BIT(8)
#define GPMU_ISENSE_STATUS GENMASK(3, 0)
#define GPMU_ISENSE_END_POINT_CAL_ERR BIT(0)
@@ -119,7 +158,6 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on);
/* A5XX_GPU_CS_AMP_CALIBRATION_STATUS*_* */
#define AMP_OUT_OF_RANGE_ERR BIT(4)
-#define AMP_CHECK_TIMEOUT_ERR BIT(3)
#define AMP_OFFSET_CHECK_MAX_ERR BIT(2)
#define AMP_OFFSET_CHECK_MIN_ERR BIT(1)
@@ -139,20 +177,12 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on);
#define PWR_THRESHOLD_VALID 0x80000000
/* AGC */
#define AGC_INIT_BASE A5XX_GPMU_DATA_RAM_BASE
-#define AGC_RVOUS_MAGIC (AGC_INIT_BASE + 0)
-#define AGC_KMD_GPMU_ADDR (AGC_INIT_BASE + 1)
-#define AGC_KMD_GPMU_BYTES (AGC_INIT_BASE + 2)
-#define AGC_GPMU_KMD_ADDR (AGC_INIT_BASE + 3)
-#define AGC_GPMU_KMD_BYTES (AGC_INIT_BASE + 4)
#define AGC_INIT_MSG_MAGIC (AGC_INIT_BASE + 5)
-#define AGC_RESERVED (AGC_INIT_BASE + 6)
#define AGC_MSG_BASE (AGC_INIT_BASE + 7)
#define AGC_MSG_STATE (AGC_MSG_BASE + 0)
#define AGC_MSG_COMMAND (AGC_MSG_BASE + 1)
-#define AGC_MSG_RETURN (AGC_MSG_BASE + 2)
#define AGC_MSG_PAYLOAD_SIZE (AGC_MSG_BASE + 3)
-#define AGC_MSG_MAX_RETURN_SIZE (AGC_MSG_BASE + 4)
#define AGC_MSG_PAYLOAD (AGC_MSG_BASE + 5)
#define AGC_INIT_MSG_VALUE 0xBABEFACE
@@ -160,14 +190,9 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on);
#define AGC_LM_CONFIG (136/4)
#define AGC_LM_CONFIG_ENABLE_GPMU_ADAPTIVE (1)
-#define AGC_LM_CONFIG_ENABLE_GPMU_LEGACY (2)
-#define AGC_LM_CONFIG_ENABLE_GPMU_LLM (3)
-#define AGC_LM_CONFIG_ENABLE_ISENSE (1 << 4)
-#define AGC_LM_CONFIG_ENABLE_DPM (2 << 4)
#define AGC_LM_CONFIG_ENABLE_ERROR (3 << 4)
-#define AGC_THROTTLE_SEL_CRC (0 << 8)
#define AGC_THROTTLE_SEL_DCS (1 << 8)
#define AGC_LLM_ENABLED (1 << 16)
@@ -177,12 +202,9 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on);
#define AGC_LEVEL_CONFIG (140/4)
-#define AGC_LEVEL_CONFIG_SENSOR_DISABLE GENMASK(15, 0)
-#define AGC_LEVEL_CONFIG_LMDISABLE GENMASK(31, 16)
#define LM_DCVS_LIMIT 2
/* FW file tages */
-#define GPMU_HEADER_ID 1
#define GPMU_FIRMWARE_ID 2
#define GPMU_SEQUENCE_ID 3
#define GPMU_INST_RAM_SIZE 0xFFF
@@ -196,7 +218,6 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on);
#define MAX_HEADER_SIZE 10
#define LM_SEQUENCE_ID 1
-#define HWCG_SEQUENCE_ID 2
#define MAX_SEQUENCE_ID 3
/* LM defaults */
diff --git a/drivers/gpu/msm/adreno_a5xx_snapshot.c b/drivers/gpu/msm/adreno_a5xx_snapshot.c
index 3d1f81fb01f7..154f5af99ffe 100644
--- a/drivers/gpu/msm/adreno_a5xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a5xx_snapshot.c
@@ -783,6 +783,33 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf,
return (header->count * 8) + sizeof(*header);
}
+/* Snapshot a preemption record buffer */
+static size_t snapshot_preemption_record(struct kgsl_device *device, u8 *buf,
+ size_t remain, void *priv)
+{
+ struct kgsl_memdesc *memdesc = priv;
+
+ struct kgsl_snapshot_gpu_object_v2 *header =
+ (struct kgsl_snapshot_gpu_object_v2 *)buf;
+
+ u8 *ptr = buf + sizeof(*header);
+
+ if (remain < (SZ_64K + sizeof(*header))) {
+ SNAPSHOT_ERR_NOMEM(device, "PREEMPTION RECORD");
+ return 0;
+ }
+
+ header->size = SZ_64K >> 2;
+ header->gpuaddr = memdesc->gpuaddr;
+ header->ptbase =
+ kgsl_mmu_pagetable_get_ttbr0(device->mmu.defaultpagetable);
+ header->type = SNAPSHOT_GPU_OBJECT_GLOBAL;
+
+ memcpy(ptr, memdesc->hostptr, SZ_64K);
+
+ return SZ_64K + sizeof(*header);
+}
+
/*
* a5xx_snapshot() - A5XX GPU snapshot function
* @adreno_dev: Device being snapshotted
@@ -797,7 +824,8 @@ void a5xx_snapshot(struct adreno_device *adreno_dev,
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
struct adreno_snapshot_data *snap_data = gpudev->snapshot_data;
- unsigned int reg;
+ unsigned int reg, i;
+ struct adreno_ringbuffer *rb;
/* Disable Clock gating temporarily for the debug bus to work */
a5xx_hwcg_set(adreno_dev, false);
@@ -874,6 +902,15 @@ void a5xx_snapshot(struct adreno_device *adreno_dev,
/* Debug bus */
a5xx_snapshot_debugbus(device, snapshot);
+
+ /* Preemption record */
+ FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
+ kgsl_snapshot_add_section(device,
+ KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
+ snapshot, snapshot_preemption_record,
+ &rb->preemption_desc);
+ }
+
}
void a5xx_crashdump_init(struct adreno_device *adreno_dev)
diff --git a/drivers/gpu/msm/adreno_coresight.c b/drivers/gpu/msm/adreno_coresight.c
index 9825797039cc..02a39278ccb3 100644
--- a/drivers/gpu/msm/adreno_coresight.c
+++ b/drivers/gpu/msm/adreno_coresight.c
@@ -313,8 +313,9 @@ int adreno_coresight_init(struct adreno_device *adreno_dev)
desc.pdata = of_get_coresight_platform_data(&device->pdev->dev,
device->pdev->dev.of_node);
- if (desc.pdata == NULL)
- return -ENODEV;
+ if (IS_ERR_OR_NULL(desc.pdata))
+ return (desc.pdata == NULL) ? -ENODEV :
+ PTR_ERR(desc.pdata);
desc.type = CORESIGHT_DEV_TYPE_SOURCE;
desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS;
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 19928686eaf2..3f36a93ea110 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -2579,12 +2579,11 @@ void adreno_dispatcher_preempt_callback(struct adreno_device *adreno_dev,
int bit)
{
struct adreno_dispatcher *dispatcher = &(adreno_dev->dispatcher);
+
if (ADRENO_DISPATCHER_PREEMPT_TRIGGERED !=
- atomic_read(&dispatcher->preemption_state)) {
- KGSL_DRV_CRIT_RATELIMIT(KGSL_DEVICE(adreno_dev),
- "Preemption interrupt generated w/o trigger!\n");
+ atomic_read(&dispatcher->preemption_state))
return;
- }
+
trace_adreno_hw_preempt_trig_to_comp_int(adreno_dev->cur_rb,
adreno_dev->next_rb);
atomic_set(&dispatcher->preemption_state,
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index cef4bb4db3a0..d8498d938b6a 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -21,8 +21,6 @@
#include "adreno.h"
#include "adreno_trace.h"
-#define KGSL_INIT_REFTIMESTAMP 0x7FFFFFFF
-
static void wait_callback(struct kgsl_device *device,
struct kgsl_event_group *group, void *priv, int result)
{
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index 09683b1bb2ba..7e80247e9322 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -83,9 +83,6 @@ struct adreno_context {
/* Flag definitions for flag field in adreno_context */
-/* Set when sync timer of cmdbatch belonging to the context times out */
-#define ADRENO_CONTEXT_CMDBATCH_FLAG_FENCE_LOG BIT(0)
-
/**
* enum adreno_context_priv - Private flags for an adreno draw context
* @ADRENO_CONTEXT_FAULT - set if the context has faulted (and recovered)
diff --git a/drivers/gpu/msm/adreno_perfcounter.c b/drivers/gpu/msm/adreno_perfcounter.c
index 1779e8e7c0b7..96922972200f 100644
--- a/drivers/gpu/msm/adreno_perfcounter.c
+++ b/drivers/gpu/msm/adreno_perfcounter.c
@@ -27,13 +27,9 @@
#define VBIF2_PERF_CLR_REG_SEL_OFF 8
/* offset of enable register from select register */
#define VBIF2_PERF_EN_REG_SEL_OFF 16
-/* offset of high counter from low counter value */
-#define VBIF2_PERF_HIGH_REG_LOW_OFF 8
/* offset of clear register from the enable register */
#define VBIF2_PERF_PWR_CLR_REG_EN_OFF 8
-/* offset of high counter from low counter value */
-#define VBIF2_PERF_PWR_HIGH_REG_LOW_OFF 8
#define REG_64BIT_VAL(hi, lo, val) (((((uint64_t) hi) << 32) | lo) + val)
/*
diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h
index f81c0f20e10b..ec2c29b929c1 100644
--- a/drivers/gpu/msm/adreno_pm4types.h
+++ b/drivers/gpu/msm/adreno_pm4types.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -15,8 +15,6 @@
#include "adreno.h"
-#define CP_PKT_MASK 0xc0000000
-
#define CP_TYPE0_PKT ((unsigned int)0 << 30)
#define CP_TYPE3_PKT ((unsigned int)3 << 30)
#define CP_TYPE4_PKT ((unsigned int)4 << 28)
@@ -32,21 +30,10 @@
#define CP_PREEMPT_TOKEN 0x1E
/* Bit to set in CP_PREEMPT_TOKEN ordinal for interrupt on preemption */
#define CP_PREEMPT_ORDINAL_INTERRUPT 24
-/* copy from ME scratch RAM to a register */
-#define CP_SCRATCH_TO_REG 0x4d
-
-/* Copy from REG to ME scratch RAM */
-#define CP_REG_TO_SCRATCH 0x4a
/* Wait for memory writes to complete */
#define CP_WAIT_MEM_WRITES 0x12
-/* Conditional execution based on register comparison */
-#define CP_COND_REG_EXEC 0x47
-
-/* Memory to REG copy */
-#define CP_MEM_TO_REG 0x42
-
/* initialize CP's micro-engine */
#define CP_ME_INIT 0x48
@@ -68,12 +55,6 @@
/* switches SMMU pagetable, used on a5xx only */
#define CP_SMMU_TABLE_UPDATE 0x53
-/* wait until a read completes */
-#define CP_WAIT_UNTIL_READ 0x5c
-
-/* wait until all base/size writes from an IB_PFD packet have completed */
-#define CP_WAIT_IB_PFD_COMPLETE 0x5d
-
/* register read/modify/write */
#define CP_REG_RMW 0x21
@@ -86,9 +67,6 @@
/* write N 32-bit words to memory */
#define CP_MEM_WRITE 0x3d
-/* write CP_PROG_COUNTER value to memory */
-#define CP_MEM_WRITE_CNTR 0x4f
-
/* conditional execution of a sequence of packets */
#define CP_COND_EXEC 0x44
@@ -98,69 +76,21 @@
/* generate an event that creates a write to memory when completed */
#define CP_EVENT_WRITE 0x46
-/* generate a VS|PS_done event */
-#define CP_EVENT_WRITE_SHD 0x58
-
-/* generate a cache flush done event */
-#define CP_EVENT_WRITE_CFL 0x59
-
-/* generate a z_pass done event */
-#define CP_EVENT_WRITE_ZPD 0x5b
-
-
/* initiate fetch of index buffer and draw */
#define CP_DRAW_INDX 0x22
-/* draw using supplied indices in packet */
-#define CP_DRAW_INDX_2 0x36
-
-/* initiate fetch of index buffer and binIDs and draw */
-#define CP_DRAW_INDX_BIN 0x34
-
-/* initiate fetch of bin IDs and draw using supplied indices */
-#define CP_DRAW_INDX_2_BIN 0x35
-
/* New draw packets defined for A4XX */
#define CP_DRAW_INDX_OFFSET 0x38
#define CP_DRAW_INDIRECT 0x28
#define CP_DRAW_INDX_INDIRECT 0x29
#define CP_DRAW_AUTO 0x24
-/* begin/end initiator for viz query extent processing */
-#define CP_VIZ_QUERY 0x23
-
-/* fetch state sub-blocks and initiate shader code DMAs */
-#define CP_SET_STATE 0x25
-
/* load constant into chip and to memory */
#define CP_SET_CONSTANT 0x2d
-/* load sequencer instruction memory (pointer-based) */
-#define CP_IM_LOAD 0x27
-
-/* load sequencer instruction memory (code embedded in packet) */
-#define CP_IM_LOAD_IMMEDIATE 0x2b
-
-/* load constants from a location in memory */
-#define CP_LOAD_CONSTANT_CONTEXT 0x2e
-
/* selective invalidation of state pointers */
#define CP_INVALIDATE_STATE 0x3b
-
-/* dynamically changes shader instruction memory partition */
-#define CP_SET_SHADER_BASES 0x4A
-
-/* sets the 64-bit BIN_MASK register in the PFP */
-#define CP_SET_BIN_MASK 0x50
-
-/* sets the 64-bit BIN_SELECT register in the PFP */
-#define CP_SET_BIN_SELECT 0x51
-
-
-/* updates the current context, if needed */
-#define CP_CONTEXT_UPDATE 0x5e
-
/* generate interrupt from the command stream */
#define CP_INTERRUPT 0x40
@@ -179,12 +109,6 @@
/* Inform CP about current render mode (needed for a5xx preemption) */
#define CP_SET_RENDER_MODE 0x6C
-/* copy sequencer instruction memory to system memory */
-#define CP_IM_STORE 0x2c
-
-/* test 2 memory locations to dword values specified */
-#define CP_TEST_TWO_MEMS 0x71
-
/* Write register, ignoring context state for context sensitive registers */
#define CP_REG_WR_NO_CTXT 0x78
@@ -198,9 +122,6 @@
/* PFP waits until the FIFO between the PFP and the ME is empty */
#define CP_WAIT_FOR_ME 0x13
-/* Record the real-time when this packet is processed by PFP */
-#define CP_RECORD_PFP_TIMESTAMP 0x11
-
#define CP_SET_PROTECTED_MODE 0x5f /* sets the register protection mode */
/* Used to switch GPU between secure and non-secure modes */
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index e433a2f275e2..f1980fd92961 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -105,7 +105,6 @@ struct adreno_ringbuffer_pagetable_info {
struct adreno_ringbuffer {
uint32_t flags;
struct kgsl_memdesc buffer_desc;
- unsigned int sizedwords;
unsigned int wptr;
unsigned int rptr;
unsigned int last_wptr;
@@ -125,16 +124,6 @@ struct adreno_ringbuffer {
enum adreno_dispatcher_starve_timer_states starve_timer_state;
};
-/* enable timestamp (...scratch0) memory shadowing */
-#define GSL_RB_MEMPTRS_SCRATCH_MASK 0x1
-
-/*
- * protected mode error checking below register address 0x800
- * note: if CP_INTERRUPT packet is used then checking needs
- * to change to below register address 0x7C8
- */
-#define GSL_RB_PROTECTED_MODE_CONTROL 0x200001F2
-
/* Returns the current ringbuffer */
#define ADRENO_CURRENT_RINGBUFFER(a) ((a)->cur_rb)
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index f9834b973a4e..ca61d36a1384 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -21,9 +21,6 @@
#include "adreno_snapshot.h"
#include "adreno_a5xx.h"
-/* Number of dwords of ringbuffer history to record */
-#define NUM_DWORDS_OF_RINGBUFFER_HISTORY 100
-
#define VPC_MEMORY_BANKS 4
/* Maintain a list of the objects we see during parsing */
@@ -753,46 +750,6 @@ static size_t snapshot_global(struct kgsl_device *device, u8 *buf,
return memdesc->size + sizeof(*header);
}
-/* Snapshot a preemption record buffer */
-static size_t snapshot_preemption_record(struct kgsl_device *device, u8 *buf,
- size_t remain, void *priv)
-{
- struct kgsl_memdesc *memdesc = priv;
- struct a5xx_cp_preemption_record record;
- int size = sizeof(record);
-
- struct kgsl_snapshot_gpu_object_v2 *header =
- (struct kgsl_snapshot_gpu_object_v2 *)buf;
-
- u8 *ptr = buf + sizeof(*header);
-
- if (size == 0)
- return 0;
-
- if (remain < (size + sizeof(*header))) {
- KGSL_CORE_ERR(
- "snapshot: Not enough memory for preemption record\n");
- return 0;
- }
-
- if (memdesc->hostptr == NULL) {
- KGSL_CORE_ERR(
- "snapshot: no kernel mapping for preemption record 0x%016llX\n",
- memdesc->gpuaddr);
- return 0;
- }
-
- header->size = size >> 2;
- header->gpuaddr = memdesc->gpuaddr;
- header->ptbase =
- kgsl_mmu_pagetable_get_ttbr0(device->mmu.defaultpagetable);
- header->type = SNAPSHOT_GPU_OBJECT_GLOBAL;
-
- memcpy(ptr, memdesc->hostptr, size);
-
- return size + sizeof(*header);
-}
-
/* Snapshot IOMMU specific buffers */
static void adreno_snapshot_iommu(struct kgsl_device *device,
struct kgsl_snapshot *snapshot)
@@ -840,7 +797,6 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
unsigned int ib1size, ib2size;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
- struct adreno_ringbuffer *rb;
ib_max_objs = 0;
/* Reset the list of objects */
@@ -885,15 +841,6 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
if (kgsl_mmu_get_mmutype(device) == KGSL_MMU_TYPE_IOMMU)
adreno_snapshot_iommu(device, snapshot);
- if (ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION)) {
- FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
- kgsl_snapshot_add_section(device,
- KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
- snapshot, snapshot_preemption_record,
- &rb->preemption_desc);
- }
- }
-
/*
* Add a section that lists (gpuaddr, size, memtype) tuples of the
* hanging process
diff --git a/drivers/gpu/msm/adreno_trace.h b/drivers/gpu/msm/adreno_trace.h
index c0926cbb6a85..5f1bbb9a83b3 100644
--- a/drivers/gpu/msm/adreno_trace.h
+++ b/drivers/gpu/msm/adreno_trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -22,6 +22,9 @@
#define TRACE_INCLUDE_FILE adreno_trace
#include <linux/tracepoint.h>
+#include "adreno_a3xx.h"
+#include "adreno_a4xx.h"
+#include "adreno_a5xx.h"
TRACE_EVENT(adreno_cmdbatch_queued,
TP_PROTO(struct kgsl_cmdbatch *cmdbatch, unsigned int queued),
@@ -364,38 +367,7 @@ TRACE_EVENT(kgsl_a3xx_irq_status,
"d_name=%s status=%s",
__get_str(device_name),
__entry->status ? __print_flags(__entry->status, "|",
- { 1 << A3XX_INT_RBBM_GPU_IDLE, "RBBM_GPU_IDLE" },
- { 1 << A3XX_INT_RBBM_AHB_ERROR, "RBBM_AHB_ERR" },
- { 1 << A3XX_INT_RBBM_REG_TIMEOUT, "RBBM_REG_TIMEOUT" },
- { 1 << A3XX_INT_RBBM_ME_MS_TIMEOUT,
- "RBBM_ME_MS_TIMEOUT" },
- { 1 << A3XX_INT_RBBM_PFP_MS_TIMEOUT,
- "RBBM_PFP_MS_TIMEOUT" },
- { 1 << A3XX_INT_RBBM_ATB_BUS_OVERFLOW,
- "RBBM_ATB_BUS_OVERFLOW" },
- { 1 << A3XX_INT_VFD_ERROR, "RBBM_VFD_ERROR" },
- { 1 << A3XX_INT_CP_SW_INT, "CP_SW" },
- { 1 << A3XX_INT_CP_T0_PACKET_IN_IB,
- "CP_T0_PACKET_IN_IB" },
- { 1 << A3XX_INT_CP_OPCODE_ERROR, "CP_OPCODE_ERROR" },
- { 1 << A3XX_INT_CP_RESERVED_BIT_ERROR,
- "CP_RESERVED_BIT_ERROR" },
- { 1 << A3XX_INT_CP_HW_FAULT, "CP_HW_FAULT" },
- { 1 << A3XX_INT_CP_DMA, "CP_DMA" },
- { 1 << A3XX_INT_CP_IB2_INT, "CP_IB2_INT" },
- { 1 << A3XX_INT_CP_IB1_INT, "CP_IB1_INT" },
- { 1 << A3XX_INT_CP_RB_INT, "CP_RB_INT" },
- { 1 << A3XX_INT_CP_REG_PROTECT_FAULT,
- "CP_REG_PROTECT_FAULT" },
- { 1 << A3XX_INT_CP_RB_DONE_TS, "CP_RB_DONE_TS" },
- { 1 << A3XX_INT_CP_VS_DONE_TS, "CP_VS_DONE_TS" },
- { 1 << A3XX_INT_CP_PS_DONE_TS, "CP_PS_DONE_TS" },
- { 1 << A3XX_INT_CACHE_FLUSH_TS, "CACHE_FLUSH_TS" },
- { 1 << A3XX_INT_CP_AHB_ERROR_HALT,
- "CP_AHB_ERROR_HALT" },
- { 1 << A3XX_INT_MISC_HANG_DETECT, "MISC_HANG_DETECT" },
- { 1 << A3XX_INT_UCHE_OOB_ACCESS, "UCHE_OOB_ACCESS" })
- : "None"
+ A3XX_IRQ_FLAGS) : "None"
)
);
@@ -422,49 +394,34 @@ TRACE_EVENT(kgsl_a4xx_irq_status,
"d_name=%s status=%s",
__get_str(device_name),
__entry->status ? __print_flags(__entry->status, "|",
- { 1 << A4XX_INT_RBBM_GPU_IDLE, "RBBM_GPU_IDLE" },
- { 1 << A4XX_INT_RBBM_AHB_ERROR, "RBBM_AHB_ERR" },
- { 1 << A4XX_INT_RBBM_REG_TIMEOUT, "RBBM_REG_TIMEOUT" },
- { 1 << A4XX_INT_RBBM_ME_MS_TIMEOUT,
- "RBBM_ME_MS_TIMEOUT" },
- { 1 << A4XX_INT_RBBM_PFP_MS_TIMEOUT,
- "RBBM_PFP_MS_TIMEOUT" },
- { 1 << A4XX_INT_RBBM_ETS_MS_TIMEOUT,
- "RBBM_ETS_MS_TIMEOUT" },
- { 1 << A4XX_INT_RBBM_ASYNC_OVERFLOW,
- "RBBM_ASYNC_OVERFLOW" },
- { 1 << A4XX_INT_RBBM_GPC_ERR,
- "RBBM_GPC_ERR" },
- { 1 << A4XX_INT_CP_SW, "CP_SW" },
- { 1 << A4XX_INT_CP_OPCODE_ERROR, "CP_OPCODE_ERROR" },
- { 1 << A4XX_INT_CP_RESERVED_BIT_ERROR,
- "CP_RESERVED_BIT_ERROR" },
- { 1 << A4XX_INT_CP_HW_FAULT, "CP_HW_FAULT" },
- { 1 << A4XX_INT_CP_DMA, "CP_DMA" },
- { 1 << A4XX_INT_CP_IB2_INT, "CP_IB2_INT" },
- { 1 << A4XX_INT_CP_IB1_INT, "CP_IB1_INT" },
- { 1 << A4XX_INT_CP_RB_INT, "CP_RB_INT" },
- { 1 << A4XX_INT_CP_REG_PROTECT_FAULT,
- "CP_REG_PROTECT_FAULT" },
- { 1 << A4XX_INT_CP_RB_DONE_TS, "CP_RB_DONE_TS" },
- { 1 << A4XX_INT_CP_VS_DONE_TS, "CP_VS_DONE_TS" },
- { 1 << A4XX_INT_CP_PS_DONE_TS, "CP_PS_DONE_TS" },
- { 1 << A4XX_INT_CACHE_FLUSH_TS, "CACHE_FLUSH_TS" },
- { 1 << A4XX_INT_CP_AHB_ERROR_HALT,
- "CP_AHB_ERROR_HALT" },
- { 1 << A4XX_INT_RBBM_ATB_BUS_OVERFLOW,
- "RBBM_ATB_BUS_OVERFLOW" },
- { 1 << A4XX_INT_MISC_HANG_DETECT, "MISC_HANG_DETECT" },
- { 1 << A4XX_INT_UCHE_OOB_ACCESS, "UCHE_OOB_ACCESS" },
- { 1 << A4XX_INT_RBBM_DPM_CALC_ERR,
- "RBBM_DPM_CALC_ERR" },
- { 1 << A4XX_INT_RBBM_DPM_EPOCH_ERR,
- "RBBM_DPM_CALC_ERR" },
- { 1 << A4XX_INT_RBBM_DPM_THERMAL_YELLOW_ERR,
- "RBBM_DPM_THERMAL_YELLOW_ERR" },
- { 1 << A4XX_INT_RBBM_DPM_THERMAL_RED_ERR,
- "RBBM_DPM_THERMAL_RED_ERR" })
- : "None"
+ A4XX_IRQ_FLAGS) : "None"
+ )
+);
+
+/*
+ * Tracepoint for a5xx irq. Includes status info
+ */
+TRACE_EVENT(kgsl_a5xx_irq_status,
+
+ TP_PROTO(struct adreno_device *adreno_dev, unsigned int status),
+
+ TP_ARGS(adreno_dev, status),
+
+ TP_STRUCT__entry(
+ __string(device_name, adreno_dev->dev.name)
+ __field(unsigned int, status)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device_name, adreno_dev->dev.name);
+ __entry->status = status;
+ ),
+
+ TP_printk(
+ "d_name=%s status=%s",
+ __get_str(device_name),
+ __entry->status ? __print_flags(__entry->status, "|",
+ A5XX_IRQ_FLAGS) : "None"
)
);
@@ -601,86 +558,6 @@ TRACE_EVENT(adreno_rb_starve,
)
);
-/*
- * Tracepoint for a5xx irq. Includes status info
- */
-TRACE_EVENT(kgsl_a5xx_irq_status,
-
- TP_PROTO(struct adreno_device *adreno_dev, unsigned int status),
-
- TP_ARGS(adreno_dev, status),
-
- TP_STRUCT__entry(
- __string(device_name, adreno_dev->dev.name)
- __field(unsigned int, status)
- ),
-
- TP_fast_assign(
- __assign_str(device_name, adreno_dev->dev.name);
- __entry->status = status;
- ),
-
- TP_printk(
- "d_name=%s status=%s",
- __get_str(device_name),
- __entry->status ? __print_flags(__entry->status, "|",
- { 1 << A5XX_INT_RBBM_GPU_IDLE, "RBBM_GPU_IDLE" },
- { 1 << A5XX_INT_RBBM_AHB_ERROR, "RBBM_AHB_ERR" },
- { 1 << A5XX_INT_RBBM_TRANSFER_TIMEOUT,
- "RBBM_TRANSFER_TIMEOUT" },
- { 1 << A5XX_INT_RBBM_ME_MS_TIMEOUT,
- "RBBM_ME_MS_TIMEOUT" },
- { 1 << A5XX_INT_RBBM_PFP_MS_TIMEOUT,
- "RBBM_PFP_MS_TIMEOUT" },
- { 1 << A5XX_INT_RBBM_ETS_MS_TIMEOUT,
- "RBBM_ETS_MS_TIMEOUT" },
- { 1 << A5XX_INT_RBBM_ATB_ASYNC_OVERFLOW,
- "RBBM_ATB_ASYNC_OVERFLOW" },
- { 1 << A5XX_INT_RBBM_GPC_ERROR,
- "RBBM_GPC_ERR" },
- { 1 << A5XX_INT_CP_SW, "CP_SW" },
- { 1 << A5XX_INT_CP_HW_ERROR, "CP_OPCODE_ERROR" },
- { 1 << A5XX_INT_CP_CCU_FLUSH_DEPTH_TS,
- "CP_CCU_FLUSH_DEPTH_TS" },
- { 1 << A5XX_INT_CP_CCU_FLUSH_COLOR_TS,
- "CP_CCU_FLUSH_COLOR_TS" },
- { 1 << A5XX_INT_CP_CCU_RESOLVE_TS,
- "CP_CCU_RESOLVE_TS" },
- { 1 << A5XX_INT_CP_IB2, "CP_IB2_INT" },
- { 1 << A5XX_INT_CP_IB1, "CP_IB1_INT" },
- { 1 << A5XX_INT_CP_RB, "CP_RB_INT" },
- { 1 << A5XX_INT_CP_UNUSED_1, "CP_UNUSED_1" },
- { 1 << A5XX_INT_CP_RB_DONE_TS, "CP_RB_DONE_TS" },
- { 1 << A5XX_INT_CP_WT_DONE_TS, "CP_WT_DONE_TS" },
- { 1 << A5XX_INT_UNKNOWN_1, "UNKNOWN_1" },
- { 1 << A5XX_INT_CP_CACHE_FLUSH_TS,
- "CP_CACHE_FLUSH_TS" },
- { 1 << A5XX_INT_UNUSED_2,
- "UNUSED_2" },
- { 1 << A5XX_INT_RBBM_ATB_BUS_OVERFLOW,
- "RBBM_ATB_BUS_OVERFLOW" },
- { 1 << A5XX_INT_MISC_HANG_DETECT,
- "MISC_HANG_DETECT" },
- { 1 << A5XX_INT_UCHE_OOB_ACCESS,
- "UCHE_OOB_ACCESS" },
- { 1 << A5XX_INT_UCHE_TRAP_INTR,
- "UCHE_TRAP_INTR" },
- { 1 << A5XX_INT_DEBBUS_INTR_0,
- "DEBBUS_INTR_0" },
- { 1 << A5XX_INT_DEBBUS_INTR_1,
- "DEBBUS_INTR_1" },
- { 1 << A5XX_INT_GPMU_VOLTAGE_DROOP,
- "GPMU_VOLTAGE_DROOP" },
- { 1 << A5XX_INT_GPMU_FIRMWARE,
- "GPMU_FIRMWARE" },
- { 1 << A5XX_INT_ISDB_CPU_IRQ,
- "ISDB_CPU_IRQ" },
- { 1 << A5XX_INT_ISDB_UNDER_DEBUG,
- "ISDB_UNDER_DEBUG" })
- : "None"
- )
-);
-
#endif /* _ADRENO_TRACE_H */
/* This part must be outside protection */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 77494ebb2c92..51dc781b2bd4 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -41,6 +41,7 @@
#include "kgsl_trace.h"
#include "kgsl_sync.h"
#include "kgsl_compat.h"
+#include "kgsl_pool.h"
#undef MODULE_PARAM_PREFIX
#define MODULE_PARAM_PREFIX "kgsl."
@@ -1785,12 +1786,8 @@ long kgsl_ioctl_sharedmem_free(struct kgsl_device_private *dev_priv,
long ret;
entry = kgsl_sharedmem_find(private, (uint64_t) param->gpuaddr);
- if (entry == NULL) {
- KGSL_MEM_INFO(dev_priv->device,
- "Invalid GPU address 0x%016llx\n",
- (uint64_t) param->gpuaddr);
+ if (entry == NULL)
return -EINVAL;
- }
ret = gpumem_free_entry(entry);
kgsl_mem_entry_put(entry);
@@ -1807,11 +1804,8 @@ long kgsl_ioctl_gpumem_free_id(struct kgsl_device_private *dev_priv,
long ret;
entry = kgsl_sharedmem_find_id(private, param->id);
- if (entry == NULL) {
- KGSL_MEM_INFO(dev_priv->device,
- "Invalid GPU memory object ID %d\n", param->id);
+ if (entry == NULL)
return -EINVAL;
- }
ret = gpumem_free_entry(entry);
kgsl_mem_entry_put(entry);
@@ -1900,11 +1894,8 @@ long kgsl_ioctl_gpuobj_free(struct kgsl_device_private *dev_priv,
long ret;
entry = kgsl_sharedmem_find_id(private, param->id);
- if (entry == NULL) {
- KGSL_MEM_ERR(dev_priv->device,
- "Invalid GPU memory object ID %d\n", param->id);
+ if (entry == NULL)
return -EINVAL;
- }
/* If no event is specified then free immediately */
if (!(param->flags & KGSL_GPUOBJ_FREE_ON_EVENT))
@@ -1939,17 +1930,14 @@ long kgsl_ioctl_cmdstream_freememontimestamp_ctxtid(
entry = kgsl_sharedmem_find(dev_priv->process_priv,
(uint64_t) param->gpuaddr);
if (entry == NULL) {
- KGSL_MEM_ERR(dev_priv->device,
- "Invalid GPU address 0x%016llx\n",
- (uint64_t) param->gpuaddr);
- goto out;
+ kgsl_context_put(context);
+ return -EINVAL;
}
ret = gpumem_free_entry_on_timestamp(dev_priv->device, entry,
context, param->timestamp);
kgsl_mem_entry_put(entry);
-out:
kgsl_context_put(context);
return ret;
@@ -2553,7 +2541,6 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
private->pagetable, entry, param->fd);
break;
default:
- KGSL_CORE_ERR("Invalid memory type: %x\n", memtype);
result = -EOPNOTSUPP;
break;
}
@@ -2563,10 +2550,6 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
if ((param->flags & KGSL_MEMFLAGS_SECURE) &&
(entry->memdesc.size & mmu->secure_align_mask)) {
- KGSL_DRV_ERR(dev_priv->device,
- "Secure buffer size %lld not aligned to %x alignment",
- entry->memdesc.size,
- mmu->secure_align_mask + 1);
result = -EINVAL;
goto error_attach;
}
@@ -2668,24 +2651,13 @@ long kgsl_ioctl_gpumem_sync_cache(struct kgsl_device_private *dev_priv,
struct kgsl_mem_entry *entry = NULL;
long ret;
- if (param->id != 0) {
+ if (param->id != 0)
entry = kgsl_sharedmem_find_id(private, param->id);
- if (entry == NULL) {
- KGSL_MEM_INFO(dev_priv->device, "can't find id %d\n",
- param->id);
- return -EINVAL;
- }
- } else if (param->gpuaddr != 0) {
+ else if (param->gpuaddr != 0)
entry = kgsl_sharedmem_find(private, (uint64_t) param->gpuaddr);
- if (entry == NULL) {
- KGSL_MEM_INFO(dev_priv->device,
- "can't find gpuaddr 0x%08lX\n",
- param->gpuaddr);
- return -EINVAL;
- }
- } else {
+
+ if (entry == NULL)
return -EINVAL;
- }
ret = _kgsl_gpumem_sync_cache(entry, (uint64_t) param->offset,
(uint64_t) param->length, param->op);
@@ -2813,12 +2785,8 @@ long kgsl_ioctl_sharedmem_flush_cache(struct kgsl_device_private *dev_priv,
long ret;
entry = kgsl_sharedmem_find(private, (uint64_t) param->gpuaddr);
- if (entry == NULL) {
- KGSL_MEM_INFO(dev_priv->device,
- "can't find gpuaddr 0x%08lX\n",
- param->gpuaddr);
+ if (entry == NULL)
return -EINVAL;
- }
ret = _kgsl_gpumem_sync_cache(entry, 0, entry->memdesc.size,
KGSL_GPUMEM_CACHE_FLUSH);
@@ -3106,15 +3074,12 @@ long kgsl_ioctl_gpumem_get_info(struct kgsl_device_private *dev_priv,
struct kgsl_mem_entry *entry = NULL;
int result = 0;
- if (param->id != 0) {
+ if (param->id != 0)
entry = kgsl_sharedmem_find_id(private, param->id);
- if (entry == NULL)
- return -EINVAL;
- } else if (param->gpuaddr != 0) {
+ else if (param->gpuaddr != 0)
entry = kgsl_sharedmem_find(private, (uint64_t) param->gpuaddr);
- if (entry == NULL)
- return -EINVAL;
- } else
+
+ if (entry == NULL)
return -EINVAL;
/*
@@ -3979,6 +3944,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
/* Initialize common sysfs entries */
kgsl_pwrctrl_init_sysfs(device);
+ /* Initialize the memory pools */
+ kgsl_init_page_pools();
+
return 0;
error_close_mmu:
@@ -3997,6 +3965,8 @@ void kgsl_device_platform_remove(struct kgsl_device *device)
kgsl_device_snapshot_close(device);
+ kgsl_exit_page_pools();
+
kgsl_pwrctrl_uninit_sysfs(device);
pm_qos_remove_request(&device->pwrctrl.pm_qos_req_dma);
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index 1f10a333adf7..2e90f78a303c 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -72,8 +72,6 @@ struct cff_op_wait_irq {
unsigned char op;
} __packed;
-#define CFF_OP_RMW 0x0000000a
-
struct cff_op_write_mem {
unsigned char op;
uint addr;
diff --git a/drivers/gpu/msm/kgsl_compat.h b/drivers/gpu/msm/kgsl_compat.h
index b7a1eb174baf..ca1685e5fcf5 100644
--- a/drivers/gpu/msm/kgsl_compat.h
+++ b/drivers/gpu/msm/kgsl_compat.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -92,16 +92,6 @@ struct kgsl_ringbuffer_issueibcmds_compat {
#define IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS_COMPAT \
_IOWR(KGSL_IOC_TYPE, 0x10, struct kgsl_ringbuffer_issueibcmds_compat)
-struct kgsl_cmdstream_freememontimestamp_compat {
- compat_ulong_t gpuaddr;
- unsigned int type;
- unsigned int timestamp;
-};
-
-#define IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_COMPAT \
- _IOW(KGSL_IOC_TYPE, 0x12, \
- struct kgsl_cmdstream_freememontimestamp_compat)
-
struct kgsl_cmdstream_freememontimestamp_ctxtid_compat {
unsigned int context_id;
compat_ulong_t gpuaddr;
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index b0540a3830ee..c3fb2b81fcbd 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -27,10 +27,6 @@
#include "kgsl_sharedmem.h"
#include "kgsl_cmdbatch.h"
-#define KGSL_TIMEOUT_NONE 0
-#define KGSL_TIMEOUT_DEFAULT 0xFFFFFFFF
-#define KGSL_TIMEOUT_PART 50 /* 50 msec */
-
#define KGSL_IOCTL_FUNC(_cmd, _func) \
[_IOC_NR((_cmd))] = \
{ .cmd = (_cmd), .func = (_func) }
@@ -53,10 +49,6 @@
#define KGSL_STATE_SLUMBER 0x00000080
#define KGSL_STATE_DEEP_NAP 0x00000100
-#define KGSL_GRAPHICS_MEMORY_LOW_WATERMARK 0x1000000
-
-#define KGSL_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))
-
/**
* enum kgsl_event_results - result codes passed to an event callback when the
* event is retired or cancelled
@@ -342,14 +334,10 @@ struct kgsl_process_private;
* @priv: in-kernel context flags, use KGSL_CONTEXT_* values
* @reset_status: status indication whether a gpu reset occured and whether
* this context was responsible for causing it
- * @wait_on_invalid_ts: flag indicating if this context has tried to wait on a
- * bad timestamp
* @timeline: sync timeline used to create fences that can be signaled when a
* sync_pt timestamp expires
* @events: A kgsl_event_group for this context - contains the list of GPU
* events
- * @pagefault_ts: global timestamp of the pagefault, if KGSL_CONTEXT_PAGEFAULT
- * is set.
* @flags: flags from userspace controlling the behavior of this context
* @pwr_constraint: power constraint from userspace for this context
* @fault_count: number of times gpu hanged in last _context_throttle_time ms
@@ -365,10 +353,8 @@ struct kgsl_context {
unsigned long priv;
struct kgsl_device *device;
unsigned int reset_status;
- bool wait_on_invalid_ts;
struct sync_timeline *timeline;
struct kgsl_event_group events;
- unsigned int pagefault_ts;
unsigned int flags;
struct kgsl_pwr_constraint pwr_constraint;
unsigned int fault_count;
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index aecb62cd1543..a338559ac0bb 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -227,9 +227,11 @@ static int _attach_pt(struct kgsl_iommu_pt *iommu_pt,
return ret;
}
-static int _lock_if_secure_mmu(struct kgsl_device *device,
- struct kgsl_memdesc *memdesc, struct kgsl_mmu *mmu)
+static int _lock_if_secure_mmu(struct kgsl_memdesc *memdesc,
+ struct kgsl_mmu *mmu)
{
+ struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
+
if (!kgsl_memdesc_is_secured(memdesc))
return 0;
@@ -245,9 +247,11 @@ static int _lock_if_secure_mmu(struct kgsl_device *device,
return 0;
}
-static void _unlock_if_secure_mmu(struct kgsl_device *device,
- struct kgsl_memdesc *memdesc, struct kgsl_mmu *mmu)
+static void _unlock_if_secure_mmu(struct kgsl_memdesc *memdesc,
+ struct kgsl_mmu *mmu)
{
+ struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
+
if (!kgsl_memdesc_is_secured(memdesc) || !kgsl_mmu_is_secured(mmu))
return;
@@ -260,11 +264,10 @@ static int _iommu_map_sync_pc(struct kgsl_pagetable *pt,
uint64_t gpuaddr, phys_addr_t physaddr,
uint64_t size, unsigned int flags)
{
- struct kgsl_device *device = KGSL_MMU_DEVICE(pt->mmu);
struct kgsl_iommu_pt *iommu_pt = pt->priv;
int ret;
- ret = _lock_if_secure_mmu(device, memdesc, pt->mmu);
+ ret = _lock_if_secure_mmu(memdesc, pt->mmu);
if (ret)
return ret;
@@ -274,7 +277,7 @@ static int _iommu_map_sync_pc(struct kgsl_pagetable *pt,
_iommu_sync_mmu_pc(false);
- _unlock_if_secure_mmu(device, memdesc, pt->mmu);
+ _unlock_if_secure_mmu(memdesc, pt->mmu);
if (ret) {
KGSL_CORE_ERR("map err: %p, 0x%016llX, 0x%llx, 0x%x, %d\n",
@@ -288,12 +291,11 @@ static int _iommu_map_sync_pc(struct kgsl_pagetable *pt,
static int _iommu_unmap_sync_pc(struct kgsl_pagetable *pt,
struct kgsl_memdesc *memdesc, uint64_t addr, uint64_t size)
{
- struct kgsl_device *device = KGSL_MMU_DEVICE(pt->mmu);
struct kgsl_iommu_pt *iommu_pt = pt->priv;
- size_t unmapped;
+ size_t unmapped = 0;
int ret;
- ret = _lock_if_secure_mmu(device, memdesc, pt->mmu);
+ ret = _lock_if_secure_mmu(memdesc, pt->mmu);
if (ret)
return ret;
@@ -303,7 +305,7 @@ static int _iommu_unmap_sync_pc(struct kgsl_pagetable *pt,
_iommu_sync_mmu_pc(false);
- _unlock_if_secure_mmu(device, memdesc, pt->mmu);
+ _unlock_if_secure_mmu(memdesc, pt->mmu);
if (unmapped != size) {
KGSL_CORE_ERR("unmap err: %p, 0x%016llx, 0x%llx, %zd\n",
@@ -314,32 +316,100 @@ static int _iommu_unmap_sync_pc(struct kgsl_pagetable *pt,
return 0;
}
+static int _iommu_map_sg_offset_sync_pc(struct kgsl_pagetable *pt,
+ uint64_t addr, struct kgsl_memdesc *memdesc,
+ struct scatterlist *sg, int nents,
+ uint64_t offset, uint64_t size, unsigned int flags)
+{
+ struct kgsl_iommu_pt *iommu_pt = pt->priv;
+ uint64_t offset_tmp = offset;
+ uint64_t size_tmp = size;
+ size_t mapped = 0;
+ unsigned int i;
+ struct scatterlist *s;
+ phys_addr_t physaddr;
+ int ret;
+
+ ret = _lock_if_secure_mmu(memdesc, pt->mmu);
+ if (ret)
+ return ret;
+
+ _iommu_sync_mmu_pc(true);
+
+ for_each_sg(sg, s, nents, i) {
+ /* Iterate until we find the offset */
+ if (offset_tmp >= s->length) {
+ offset_tmp -= s->length;
+ continue;
+ }
+
+ /* How much mapping is needed in this sg? */
+ if (size < s->length - offset_tmp)
+ size_tmp = size;
+ else
+ size_tmp = s->length - offset_tmp;
+
+ /* Get the phys addr for the offset page */
+ if (offset_tmp != 0) {
+ physaddr = page_to_phys(nth_page(sg_page(s),
+ offset_tmp >> PAGE_SHIFT));
+ /* Reset offset_tmp */
+ offset_tmp = 0;
+ } else
+ physaddr = page_to_phys(sg_page(s));
+
+ /* Do the map for this sg */
+ ret = iommu_map(iommu_pt->domain, addr + mapped,
+ physaddr, size_tmp, flags);
+ if (ret)
+ break;
+
+ mapped += size_tmp;
+ size -= size_tmp;
+
+ if (size == 0)
+ break;
+ }
+
+ _iommu_sync_mmu_pc(false);
+
+ _unlock_if_secure_mmu(memdesc, pt->mmu);
+
+ if (size != 0) {
+ /* Cleanup on error */
+ _iommu_unmap_sync_pc(pt, memdesc, addr, mapped);
+ KGSL_CORE_ERR("map err: %p, 0x%016llX, %d, %x, %zd\n",
+ iommu_pt->domain, addr, nents, flags, mapped);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static int _iommu_map_sg_sync_pc(struct kgsl_pagetable *pt,
uint64_t addr, struct kgsl_memdesc *memdesc,
+ struct scatterlist *sg, int nents,
unsigned int flags)
{
- struct kgsl_device *device = KGSL_MMU_DEVICE(pt->mmu);
struct kgsl_iommu_pt *iommu_pt = pt->priv;
size_t mapped;
int ret;
- ret = _lock_if_secure_mmu(device, memdesc, pt->mmu);
+ ret = _lock_if_secure_mmu(memdesc, pt->mmu);
if (ret)
return ret;
_iommu_sync_mmu_pc(true);
- mapped = iommu_map_sg(iommu_pt->domain, addr, memdesc->sgt->sgl,
- memdesc->sgt->nents, flags);
+ mapped = iommu_map_sg(iommu_pt->domain, addr, sg, nents, flags);
_iommu_sync_mmu_pc(false);
- _unlock_if_secure_mmu(device, memdesc, pt->mmu);
+ _unlock_if_secure_mmu(memdesc, pt->mmu);
if (mapped == 0) {
KGSL_CORE_ERR("map err: %p, 0x%016llX, %d, %x, %zd\n",
- iommu_pt->domain, addr, memdesc->sgt->nents,
- flags, mapped);
+ iommu_pt->domain, addr, nents, flags, mapped);
return -ENODEV;
}
@@ -1404,15 +1474,34 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu)
}
static int
-kgsl_iommu_unmap(struct kgsl_pagetable *pt,
- struct kgsl_memdesc *memdesc)
+kgsl_iommu_unmap_offset(struct kgsl_pagetable *pt,
+ struct kgsl_memdesc *memdesc, uint64_t addr,
+ uint64_t offset, uint64_t size)
+{
+ /*
+ * All GPU addresses as assigned are page aligned, but some
+ * functions perturb the gpuaddr with an offset, so apply the
+ * mask here to make sure we have the right address.
+ */
+
+ addr = PAGE_ALIGN(addr);
+
+ if (size == 0 || addr == 0)
+ return 0;
+
+ return _iommu_unmap_sync_pc(pt, memdesc, addr + offset, size);
+}
+
+static int
+kgsl_iommu_unmap(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc)
{
uint64_t size = memdesc->size;
if (kgsl_memdesc_has_guard_page(memdesc))
size += kgsl_memdesc_guard_page_size(pt->mmu, memdesc);
- return _iommu_unmap_sync_pc(pt, memdesc, memdesc->gpuaddr, size);
+ return kgsl_iommu_unmap_offset(pt, memdesc, memdesc->gpuaddr, 0,
+ size);
}
/**
@@ -1472,27 +1561,30 @@ static int _iommu_map_guard_page(struct kgsl_pagetable *pt,
protflags & ~IOMMU_WRITE);
}
-static int
-kgsl_iommu_map(struct kgsl_pagetable *pt,
- struct kgsl_memdesc *memdesc)
+static unsigned int _get_protection_flags(struct kgsl_memdesc *memdesc)
{
- int ret;
- uint64_t addr = memdesc->gpuaddr;
- uint64_t size = memdesc->size;
- unsigned int flags;
-
- BUG_ON(NULL == pt->priv);
-
- flags = IOMMU_READ | IOMMU_WRITE | IOMMU_NOEXEC;
+ unsigned int flags = IOMMU_READ | IOMMU_WRITE | IOMMU_NOEXEC;
- /* Set up the protection for the page(s) */
if (memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY)
flags &= ~IOMMU_WRITE;
if (memdesc->priv & KGSL_MEMDESC_PRIVILEGED)
flags |= IOMMU_PRIV;
- ret = _iommu_map_sg_sync_pc(pt, addr, memdesc, flags);
+ return flags;
+}
+
+static int
+kgsl_iommu_map(struct kgsl_pagetable *pt,
+ struct kgsl_memdesc *memdesc)
+{
+ int ret;
+ uint64_t addr = memdesc->gpuaddr;
+ uint64_t size = memdesc->size;
+ unsigned int flags = _get_protection_flags(memdesc);
+
+ ret = _iommu_map_sg_sync_pc(pt, addr, memdesc, memdesc->sgt->sgl,
+ memdesc->sgt->nents, flags);
if (ret)
return ret;
@@ -1503,6 +1595,26 @@ kgsl_iommu_map(struct kgsl_pagetable *pt,
return ret;
}
+static int kgsl_iommu_map_offset(struct kgsl_pagetable *pt,
+ uint64_t virtaddr, uint64_t virtoffset,
+ struct kgsl_memdesc *memdesc, uint64_t physoffset,
+ uint64_t size, uint64_t feature_flag)
+{
+ int pg_sz;
+ unsigned int protflags = _get_protection_flags(memdesc);
+
+ pg_sz = (1 << kgsl_memdesc_get_align(memdesc));
+ if (!IS_ALIGNED(virtaddr | virtoffset | physoffset | size, pg_sz))
+ return -EINVAL;
+
+ if (size == 0)
+ return -EINVAL;
+
+ return _iommu_map_sg_offset_sync_pc(pt, virtaddr + virtoffset,
+ memdesc, memdesc->sgt->sgl, memdesc->sgt->nents,
+ physoffset, size, protflags);
+}
+
/* This function must be called with context bank attached */
static void kgsl_iommu_clear_fsr(struct kgsl_mmu *mmu)
{
@@ -2270,4 +2382,6 @@ static struct kgsl_mmu_pt_ops iommu_pt_ops = {
.find_svm_region = kgsl_iommu_find_svm_region,
.svm_range = kgsl_iommu_svm_range,
.addr_in_range = kgsl_iommu_addr_in_range,
+ .mmu_map_offset = kgsl_iommu_map_offset,
+ .mmu_unmap_offset = kgsl_iommu_unmap_offset,
};
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index f82452dd6080..06f6d65effad 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -45,20 +45,6 @@
#define KGSL_IOMMU_SVM_BASE64 0x700000000ULL
#define KGSL_IOMMU_SVM_END64 0x800000000ULL
-/* Pagetable virtual base */
-#define KGSL_IOMMU_CTX_OFFSET_V1 0x8000
-#define KGSL_IOMMU_CTX_OFFSET_V2 0x9000
-#define KGSL_IOMMU_CTX_OFFSET_V2_A530 0x8000
-#define KGSL_IOMMU_CTX_OFFSET_A405V2 0x8000
-#define KGSL_IOMMU_CTX_SHIFT 12
-
-/* FSYNR1 V0 fields */
-#define KGSL_IOMMU_FSYNR1_AWRITE_MASK 0x00000001
-#define KGSL_IOMMU_FSYNR1_AWRITE_SHIFT 8
-/* FSYNR0 V1 fields */
-#define KGSL_IOMMU_V1_FSYNR0_WNR_MASK 0x00000001
-#define KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT 4
-
/* TLBSTATUS register fields */
#define KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE BIT(0)
diff --git a/drivers/gpu/msm/kgsl_log.h b/drivers/gpu/msm/kgsl_log.h
index 70480f8e9189..51baabefb6d3 100644
--- a/drivers/gpu/msm/kgsl_log.h
+++ b/drivers/gpu/msm/kgsl_log.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011,2013-2014 The Linux Foundation.
+/* Copyright (c) 2002,2008-2011,2013-2014,2016 The Linux Foundation.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -48,9 +48,6 @@
BUG(); \
} while (0)
-#define KGSL_LOG_POSTMORTEM_WRITE(_dev, fmt, args...) \
- do { dev_crit(_dev->dev, fmt, ##args); } while (0)
-
#define KGSL_LOG_DUMP(_dev, fmt, args...) dev_err(_dev->dev, fmt, ##args)
#define KGSL_DEV_ERR_ONCE(_dev, fmt, args...) \
@@ -83,24 +80,6 @@ KGSL_LOG_CRIT_RATELIMITED(_dev->dev, _dev->drv_log, fmt, ##args)
#define KGSL_DRV_FATAL(_dev, fmt, args...) \
KGSL_LOG_FATAL((_dev)->dev, (_dev)->drv_log, fmt, ##args)
-#define KGSL_CMD_INFO(_dev, fmt, args...) \
-KGSL_LOG_INFO(_dev->dev, _dev->cmd_log, fmt, ##args)
-#define KGSL_CMD_WARN(_dev, fmt, args...) \
-KGSL_LOG_WARN(_dev->dev, _dev->cmd_log, fmt, ##args)
-#define KGSL_CMD_ERR(_dev, fmt, args...) \
-KGSL_LOG_ERR(_dev->dev, _dev->cmd_log, fmt, ##args)
-#define KGSL_CMD_CRIT(_dev, fmt, args...) \
-KGSL_LOG_CRIT(_dev->dev, _dev->cmd_log, fmt, ##args)
-
-#define KGSL_CTXT_INFO(_dev, fmt, args...) \
-KGSL_LOG_INFO(_dev->dev, _dev->ctxt_log, fmt, ##args)
-#define KGSL_CTXT_WARN(_dev, fmt, args...) \
-KGSL_LOG_WARN(_dev->dev, _dev->ctxt_log, fmt, ##args)
-#define KGSL_CTXT_ERR(_dev, fmt, args...) \
-KGSL_LOG_ERR(_dev->dev, _dev->ctxt_log, fmt, ##args)
-#define KGSL_CTXT_CRIT(_dev, fmt, args...) \
-KGSL_LOG_CRIT(_dev->dev, _dev->ctxt_log, fmt, ##args)
-
#define KGSL_MEM_INFO(_dev, fmt, args...) \
KGSL_LOG_INFO(_dev->dev, _dev->mem_log, fmt, ##args)
#define KGSL_MEM_WARN(_dev, fmt, args...) \
@@ -125,13 +104,4 @@ KGSL_LOG_CRIT(_dev->dev, _dev->pwr_log, fmt, ##args)
#define KGSL_CORE_ERR(fmt, args...) \
pr_err("kgsl: %s: " fmt, __func__, ##args)
-#define KGSL_CORE_ERR_ONCE(fmt, args...) \
-({ \
- static bool kgsl_core_err_once; \
- if (!kgsl_core_err_once) { \
- kgsl_core_err_once = true; \
- pr_err("kgsl: %s: " fmt, __func__, ##args); \
- } \
-})
-
#endif /* __KGSL_LOG_H */
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 82150fbe9ac1..f8315090ff06 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -476,6 +476,31 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
}
EXPORT_SYMBOL(kgsl_mmu_unmap);
+int kgsl_mmu_map_offset(struct kgsl_pagetable *pagetable,
+ uint64_t virtaddr, uint64_t virtoffset,
+ struct kgsl_memdesc *memdesc, uint64_t physoffset,
+ uint64_t size, uint64_t flags)
+{
+ if (PT_OP_VALID(pagetable, mmu_map_offset))
+ return pagetable->pt_ops->mmu_map_offset(pagetable, virtaddr,
+ virtoffset, memdesc, physoffset, size, flags);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(kgsl_mmu_map_offset);
+
+int kgsl_mmu_unmap_offset(struct kgsl_pagetable *pagetable,
+ struct kgsl_memdesc *memdesc, uint64_t addr, uint64_t offset,
+ uint64_t size)
+{
+ if (PT_OP_VALID(pagetable, mmu_unmap_offset))
+ return pagetable->pt_ops->mmu_unmap_offset(pagetable, memdesc,
+ addr, offset, size);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(kgsl_mmu_unmap_offset);
+
void kgsl_mmu_remove_global(struct kgsl_device *device,
struct kgsl_memdesc *memdesc)
{
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 576a6acd4538..3652aa2e6ec4 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -92,6 +92,13 @@ struct kgsl_mmu_pt_ops {
int (*svm_range)(struct kgsl_pagetable *, uint64_t *, uint64_t *,
uint64_t);
bool (*addr_in_range)(struct kgsl_pagetable *pagetable, uint64_t);
+ int (*mmu_map_offset)(struct kgsl_pagetable *pt,
+ uint64_t virtaddr, uint64_t virtoffset,
+ struct kgsl_memdesc *memdesc, uint64_t physoffset,
+ uint64_t size, uint64_t flags);
+ int (*mmu_unmap_offset)(struct kgsl_pagetable *pt,
+ struct kgsl_memdesc *memdesc, uint64_t addr,
+ uint64_t offset, uint64_t size);
};
/*
@@ -206,6 +213,14 @@ struct kgsl_pagetable *kgsl_get_pagetable(unsigned long name);
struct kgsl_pagetable *
kgsl_mmu_createpagetableobject(struct kgsl_mmu *mmu, unsigned int name);
+int kgsl_mmu_map_offset(struct kgsl_pagetable *pagetable,
+ uint64_t virtaddr, uint64_t virtoffset,
+ struct kgsl_memdesc *memdesc, uint64_t physoffset,
+ uint64_t size, uint64_t flags);
+int kgsl_mmu_unmap_offset(struct kgsl_pagetable *pagetable,
+ struct kgsl_memdesc *memdesc, uint64_t addr, uint64_t offset,
+ uint64_t size);
+
/*
* Static inline functions of MMU that simply call the SMMU specific
* function using a function pointer. These functions can be thought
diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c
new file mode 100644
index 000000000000..497cfdaae2ec
--- /dev/null
+++ b/drivers/gpu/msm/kgsl_pool.c
@@ -0,0 +1,341 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/vmalloc.h>
+#include <asm/cacheflush.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/version.h>
+
+#include "kgsl.h"
+#include "kgsl_device.h"
+#include "kgsl_pool.h"
+
+/*
+ * Maximum pool size in terms of pages
+ * = (Number of pools * Max size per pool)
+ */
+#define KGSL_POOL_MAX_PAGES (2 * 4096)
+
+/* Set the max pool size to 8192 pages */
+static unsigned int kgsl_pool_max_pages = KGSL_POOL_MAX_PAGES;
+
+struct kgsl_page_pool {
+ unsigned int pool_order;
+ int page_count;
+ spinlock_t list_lock;
+ struct list_head page_list;
+};
+
+static struct kgsl_page_pool kgsl_pools[] = {
+ {
+ .pool_order = 0,
+ .list_lock = __SPIN_LOCK_UNLOCKED(kgsl_pools[0].list_lock),
+ .page_list = LIST_HEAD_INIT(kgsl_pools[0].page_list),
+ },
+#ifndef CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS
+ {
+ .pool_order = 4,
+ .list_lock = __SPIN_LOCK_UNLOCKED(kgsl_pools[1].list_lock),
+ .page_list = LIST_HEAD_INIT(kgsl_pools[1].page_list),
+ },
+#endif
+};
+
+#define KGSL_NUM_POOLS ARRAY_SIZE(kgsl_pools)
+
+/* Returns KGSL pool corresponding to input page order*/
+static struct kgsl_page_pool *
+_kgsl_get_pool_from_order(unsigned int order)
+{
+ int i;
+
+ for (i = 0; i < KGSL_NUM_POOLS; i++) {
+ if (kgsl_pools[i].pool_order == order)
+ return &kgsl_pools[i];
+ }
+
+ return NULL;
+}
+
+/* Add a page to specified pool */
+static void
+_kgsl_pool_add_page(struct kgsl_page_pool *pool, struct page *p)
+{
+ spin_lock(&pool->list_lock);
+ list_add_tail(&p->lru, &pool->page_list);
+ pool->page_count++;
+ spin_unlock(&pool->list_lock);
+}
+
+/* Returns a page from specified pool */
+static struct page *
+_kgsl_pool_get_page(struct kgsl_page_pool *pool)
+{
+ struct page *p = NULL;
+
+ spin_lock(&pool->list_lock);
+ if (pool->page_count) {
+ p = list_first_entry(&pool->page_list, struct page, lru);
+ pool->page_count--;
+ list_del(&p->lru);
+ }
+ spin_unlock(&pool->list_lock);
+
+ return p;
+}
+
+/* Returns the number of pages in specified pool */
+static int
+kgsl_pool_size(struct kgsl_page_pool *kgsl_pool)
+{
+ int size;
+
+ spin_lock(&kgsl_pool->list_lock);
+ size = kgsl_pool->page_count * (1 << kgsl_pool->pool_order);
+ spin_unlock(&kgsl_pool->list_lock);
+
+ return size;
+}
+
+/* Returns the number of pages in all kgsl page pools */
+static int kgsl_pool_size_total(void)
+{
+ int i;
+ int total = 0;
+
+ for (i = 0; i < KGSL_NUM_POOLS; i++)
+ total += kgsl_pool_size(&kgsl_pools[i]);
+ return total;
+}
+
+/*
+ * This will shrink the specified pool by num_pages or its pool_size,
+ * whichever is smaller.
+ */
+static unsigned int
+_kgsl_pool_shrink(struct kgsl_page_pool *pool, int num_pages)
+{
+ int j;
+ unsigned int pcount = 0;
+
+ if (pool == NULL || num_pages <= 0)
+ return pcount;
+
+ for (j = 0; j < num_pages >> pool->pool_order; j++) {
+ struct page *page = _kgsl_pool_get_page(pool);
+
+ if (page != NULL) {
+ __free_pages(page, pool->pool_order);
+ pcount += (1 << pool->pool_order);
+ } else {
+ /* Break as this pool is empty */
+ break;
+ }
+ }
+
+ return pcount;
+}
+
+/*
+ * This function reduces the total pool size
+ * to number of pages specified by target_pages.
+ *
+ * If target_pages are greater than current pool size
+ * nothing needs to be done otherwise remove
+ * (current_pool_size - target_pages) pages from pool
+ * starting from higher order pool.
+ */
+static int
+kgsl_pool_reduce(unsigned int target_pages)
+{
+ int total_pages = 0;
+ int i;
+ int nr_removed;
+ struct kgsl_page_pool *pool;
+ unsigned int pcount = 0;
+
+ total_pages = kgsl_pool_size_total();
+
+ for (i = (KGSL_NUM_POOLS - 1); i >= 0; i--) {
+ pool = &kgsl_pools[i];
+
+ total_pages -= pcount;
+
+ nr_removed = total_pages - target_pages;
+ if (nr_removed <= 0)
+ return pcount;
+
+ /* Round up to integral number of pages in this pool */
+ nr_removed = ALIGN(nr_removed, 1 << pool->pool_order);
+
+ /* Remove nr_removed pages from this pool*/
+ pcount += _kgsl_pool_shrink(pool, nr_removed);
+ }
+
+ return pcount;
+}
+
+/**
+ * kgsl_pool_free_sgt() - Free scatter-gather list
+ * @sgt: pointer of the sg list
+ *
+ * Free the sg list by collapsing any physical adjacent pages.
+ * Pages are added back to the pool, if pool has sufficient space
+ * otherwise they are given back to system.
+ */
+
+void kgsl_pool_free_sgt(struct sg_table *sgt)
+{
+ int i;
+ struct scatterlist *sg;
+
+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+ /*
+ * sg_alloc_table_from_pages() will collapse any physically
+ * adjacent pages into a single scatterlist entry. We cannot
+ * just call __free_pages() on the entire set since we cannot
+ * ensure that the size is a whole order. Instead, free each
+ * page or compound page group individually.
+ */
+ struct page *p = sg_page(sg), *next;
+ unsigned int count;
+ unsigned int j = 0;
+
+ while (j < (sg->length/PAGE_SIZE)) {
+ count = 1 << compound_order(p);
+ next = nth_page(p, count);
+ kgsl_pool_free_page(p);
+
+ p = next;
+ j += count;
+ }
+ }
+}
+
+/**
+ * kgsl_pool_alloc_page() - Allocate a page of requested size
+ * @page_size: Size of the page to be allocated
+ * @pages: pointer to hold list of pages, should be big enough to hold
+ * requested page
+ * @len: Length of array pages.
+ *
+ * Return total page count on success and negative value on failure
+ */
+int kgsl_pool_alloc_page(int page_size, struct page **pages,
+ unsigned int pages_len)
+{
+ int j;
+ int pcount = 0;
+ struct kgsl_page_pool *pool;
+ struct page *page = NULL;
+ struct page *p = NULL;
+
+ if ((pages == NULL) || pages_len < (page_size >> PAGE_SHIFT))
+ return -EINVAL;
+
+ pool = _kgsl_get_pool_from_order(get_order(page_size));
+
+ if (pool != NULL)
+ page = _kgsl_pool_get_page(pool);
+
+ /* Allocate a new page if not allocated from pool */
+ if (page == NULL) {
+ gfp_t gfp_mask = kgsl_gfp_mask(get_order(page_size));
+
+ page = alloc_pages(gfp_mask,
+ get_order(page_size));
+
+ if (!page)
+ return -ENOMEM;
+ }
+
+ for (j = 0; j < (page_size >> PAGE_SHIFT); j++) {
+ p = nth_page(page, j);
+ pages[pcount] = p;
+ pcount++;
+ }
+
+ return pcount;
+}
+
+void kgsl_pool_free_page(struct page *page)
+{
+ struct kgsl_page_pool *pool;
+ int page_order;
+
+ if (page == NULL)
+ return;
+
+ page_order = compound_order(page);
+
+ if (kgsl_pool_size_total() < kgsl_pool_max_pages) {
+ pool = _kgsl_get_pool_from_order(page_order);
+ if (pool != NULL) {
+ _kgsl_pool_add_page(pool, page);
+ return;
+ }
+ }
+
+ /* Give back to system as not added to pool */
+ __free_pages(page, page_order);
+}
+
+/* Functions for the shrinker */
+
+static unsigned long
+kgsl_pool_shrink_scan_objects(struct shrinker *shrinker,
+ struct shrink_control *sc)
+{
+ /* nr represents number of pages to be removed*/
+ int nr = sc->nr_to_scan;
+ int total_pages = kgsl_pool_size_total();
+
+ /* Target pages represents new pool size */
+ int target_pages = (nr > total_pages) ? 0 : (total_pages - nr);
+
+ /* Reduce pool size to target_pages */
+ return kgsl_pool_reduce(target_pages);
+}
+
+static unsigned long
+kgsl_pool_shrink_count_objects(struct shrinker *shrinker,
+ struct shrink_control *sc)
+{
+ /* Return total pool size as everything in pool can be freed */
+ return kgsl_pool_size_total();
+}
+
+/* Shrinker callback data*/
+static struct shrinker kgsl_pool_shrinker = {
+ .count_objects = kgsl_pool_shrink_count_objects,
+ .scan_objects = kgsl_pool_shrink_scan_objects,
+ .seeks = DEFAULT_SEEKS,
+ .batch = 0,
+};
+
+void kgsl_init_page_pools(void)
+{
+ /* Initialize shrinker */
+ register_shrinker(&kgsl_pool_shrinker);
+}
+
+void kgsl_exit_page_pools(void)
+{
+ /* Release all pages in pools, if any.*/
+ kgsl_pool_reduce(0);
+
+ /* Unregister shrinker */
+ unregister_shrinker(&kgsl_pool_shrinker);
+}
+
diff --git a/drivers/gpu/msm/kgsl_pool.h b/drivers/gpu/msm/kgsl_pool.h
new file mode 100644
index 000000000000..f76c8aadbf30
--- /dev/null
+++ b/drivers/gpu/msm/kgsl_pool.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __KGSL_POOL_H
+#define __KGSL_POOL_H
+
+#include <linux/mm_types.h>
+#include "kgsl_sharedmem.h"
+
+static inline unsigned int
+kgsl_gfp_mask(unsigned int page_order)
+{
+ unsigned int gfp_mask = __GFP_HIGHMEM;
+
+ if (page_order > 0) {
+ gfp_mask |= __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN;
+ gfp_mask &= ~__GFP_RECLAIM;
+ } else
+ gfp_mask |= GFP_KERNEL;
+
+ if (kgsl_sharedmem_get_noretry() == true)
+ gfp_mask |= __GFP_NORETRY | __GFP_NOWARN;
+
+ return gfp_mask;
+}
+
+void kgsl_pool_free_sgt(struct sg_table *sgt);
+void kgsl_init_page_pools(void);
+void kgsl_exit_page_pools(void);
+int kgsl_pool_alloc_page(int page_size, struct page **pages,
+ unsigned int pages_len);
+void kgsl_pool_free_page(struct page *p);
+#endif /* __KGSL_POOL_H */
+
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index f9b5545519cb..927841a7ad3b 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -35,23 +35,12 @@
#define UPDATE_BUSY_VAL 1000000
-/*
- * Expected delay for post-interrupt processing on A3xx.
- * The delay may be longer, gradually increase the delay
- * to compensate. If the GPU isn't done by max delay,
- * it's working on something other than just the final
- * command sequence so stop waiting for it to be idle.
- */
-#define INIT_UDELAY 200
-#define MAX_UDELAY 2000
-
/* Number of jiffies for a full thermal cycle */
#define TH_HZ (HZ/5)
#define KGSL_MAX_BUSLEVELS 20
#define DEFAULT_BUS_P 25
-#define DEFAULT_BUS_DIV (100 / DEFAULT_BUS_P)
/*
* The effective duration of qos request in usecs. After
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 7ed76760c043..9fcea11c805b 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -22,8 +22,6 @@
#define KGSL_PWRFLAGS_OFF 0
#define KGSL_PWRLEVEL_TURBO 0
-#define KGSL_PWRLEVEL_NOMINAL 1
-#define KGSL_PWRLEVEL_LAST_OFFSET 2
#define KGSL_PWR_ON 0xFFFF
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index 4ee1816a66f0..4f6677d9a1de 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -19,9 +19,6 @@
#include "kgsl_device.h"
#include "kgsl_trace.h"
-#define FAST_BUS 1
-#define SLOW_BUS -1
-
/*
* "SLEEP" is generic counting both NAP & SLUMBER
* PERIODS generally won't exceed 9 for the relavent 150msec
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 893e31852ccb..4cb9bc5d1651 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -27,6 +27,7 @@
#include "kgsl_device.h"
#include "kgsl_log.h"
#include "kgsl_mmu.h"
+#include "kgsl_pool.h"
/*
* The user can set this from debugfs to force failed memory allocations to
@@ -424,9 +425,6 @@ done:
static void kgsl_page_alloc_free(struct kgsl_memdesc *memdesc)
{
- unsigned int i = 0;
- struct scatterlist *sg;
-
kgsl_page_alloc_unmap_kernel(memdesc);
/* we certainly do not expect the hostptr to still be mapped */
BUG_ON(memdesc->hostptr);
@@ -451,28 +449,15 @@ static void kgsl_page_alloc_free(struct kgsl_memdesc *memdesc)
atomic_long_sub(memdesc->size, &kgsl_driver.stats.page_alloc);
}
- for_each_sg(memdesc->sgt->sgl, sg, memdesc->sgt->nents, i) {
- /*
- * sg_alloc_table_from_pages() will collapse any physically
- * adjacent pages into a single scatterlist entry. We cannot
- * just call __free_pages() on the entire set since we cannot
- * ensure that the size is a whole order. Instead, free each
- * page or compound page group individually.
- */
- struct page *p = sg_page(sg), *next;
- unsigned int j = 0, count;
- while (j < (sg->length/PAGE_SIZE)) {
- if (memdesc->priv & KGSL_MEMDESC_TZ_LOCKED)
- ClearPagePrivate(p);
-
- count = 1 << compound_order(p);
- next = nth_page(p, count);
- __free_pages(p, compound_order(p));
- p = next;
- j += count;
+ if (memdesc->priv & KGSL_MEMDESC_TZ_LOCKED) {
+ struct sg_page_iter sg_iter;
- }
+ for_each_sg_page(memdesc->sgt->sgl, &sg_iter,
+ memdesc->sgt->nents, 0)
+ ClearPagePrivate(sg_page_iter_page(&sg_iter));
}
+
+ kgsl_pool_free_sgt(memdesc->sgt);
}
/*
@@ -681,19 +666,67 @@ static inline int get_page_size(size_t size, unsigned int align)
}
#endif
+static void kgsl_zero_pages(struct page **pages, unsigned int pcount)
+{
+ unsigned int j;
+ unsigned int step = ((VMALLOC_END - VMALLOC_START)/8) >> PAGE_SHIFT;
+ pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL);
+ void *ptr;
+
+ /*
+ * All memory that goes to the user has to be zeroed out before it gets
+ * exposed to userspace. This means that the memory has to be mapped in
+ * the kernel, zeroed (memset) and then unmapped. This also means that
+ * the dcache has to be flushed to ensure coherency between the kernel
+ * and user pages. We used to pass __GFP_ZERO to alloc_page which mapped
+ * zeroed and unmaped each individual page, and then we had to turn
+ * around and call flush_dcache_page() on that page to clear the caches.
+ * This was killing us for performance. Instead, we found it is much
+ * faster to allocate the pages without GFP_ZERO, map a chunk of the
+ * range ('step' pages), memset it, flush it and then unmap
+ * - this results in a factor of 4 improvement for speed for large
+ * buffers. There is a small decrease in speed for small buffers,
+ * but only on the order of a few microseconds at best. The 'step'
+ * size is based on a guess at the amount of free vmalloc space, but
+ * will scale down if there's not enough free space.
+ */
+ for (j = 0; j < pcount; j += step) {
+ step = min(step, pcount - j);
+
+ ptr = vmap(&pages[j], step, VM_IOREMAP, page_prot);
+
+ if (ptr != NULL) {
+ memset(ptr, 0, step * PAGE_SIZE);
+ dmac_flush_range(ptr, ptr + step * PAGE_SIZE);
+ vunmap(ptr);
+ } else {
+ int k;
+ /* Very, very, very slow path */
+
+ for (k = j; k < j + step; k++) {
+ ptr = kmap_atomic(pages[k]);
+ memset(ptr, 0, PAGE_SIZE);
+ dmac_flush_range(ptr, ptr + PAGE_SIZE);
+ kunmap_atomic(ptr);
+ }
+ /* scale down the step size to avoid this path */
+ if (step > 1)
+ step >>= 1;
+ }
+ }
+}
+
static int
kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc,
struct kgsl_pagetable *pagetable,
uint64_t size)
{
int ret = 0;
- unsigned int j, pcount = 0, page_size, len_alloc;
+ unsigned int j, page_size, len_alloc;
+ unsigned int pcount = 0;
size_t len;
struct page **pages = NULL;
- pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL);
- void *ptr;
unsigned int align;
- unsigned int step = ((VMALLOC_END - VMALLOC_START)/8) >> PAGE_SHIFT;
size = PAGE_ALIGN(size);
if (size == 0 || size > UINT_MAX)
@@ -740,30 +773,16 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc,
len = size;
while (len > 0) {
- struct page *page;
- gfp_t gfp_mask = __GFP_HIGHMEM;
- int j;
+ int page_count;
/* don't waste space at the end of the allocation*/
if (len < page_size)
page_size = PAGE_SIZE;
- /*
- * Don't do some of the more aggressive memory recovery
- * techniques for large order allocations
- */
- if (page_size != PAGE_SIZE) {
- gfp_mask |= __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN;
- gfp_mask &= ~__GFP_RECLAIM;
- } else
- gfp_mask |= GFP_KERNEL;
-
- if (sharedmem_noretry_flag == true)
- gfp_mask |= __GFP_NORETRY | __GFP_NOWARN;
+ page_count = kgsl_pool_alloc_page(page_size,
+ pages + pcount, len_alloc - pcount);
- page = alloc_pages(gfp_mask, get_order(page_size));
-
- if (page == NULL) {
+ if (page_count <= 0) {
if (page_size != PAGE_SIZE) {
page_size = PAGE_SIZE;
continue;
@@ -785,9 +804,7 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc,
goto done;
}
- for (j = 0; j < page_size >> PAGE_SHIFT; j++)
- pages[pcount++] = nth_page(page, j);
-
+ pcount += page_count;
len -= page_size;
memdesc->size += page_size;
}
@@ -824,57 +841,23 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc,
goto done;
}
- /*
- * All memory that goes to the user has to be zeroed out before it gets
- * exposed to userspace. This means that the memory has to be mapped in
- * the kernel, zeroed (memset) and then unmapped. This also means that
- * the dcache has to be flushed to ensure coherency between the kernel
- * and user pages. We used to pass __GFP_ZERO to alloc_page which mapped
- * zeroed and unmaped each individual page, and then we had to turn
- * around and call flush_dcache_page() on that page to clear the caches.
- * This was killing us for performance. Instead, we found it is much
- * faster to allocate the pages without GFP_ZERO, map a chunk of the
- * range ('step' pages), memset it, flush it and then unmap
- * - this results in a factor of 4 improvement for speed for large
- * buffers. There is a small decrease in speed for small buffers,
- * but only on the order of a few microseconds at best. The 'step'
- * size is based on a guess at the amount of free vmalloc space, but
- * will scale down if there's not enough free space.
- */
- for (j = 0; j < pcount; j += step) {
- step = min(step, pcount - j);
-
- ptr = vmap(&pages[j], step, VM_IOREMAP, page_prot);
-
- if (ptr != NULL) {
- memset(ptr, 0, step * PAGE_SIZE);
- dmac_flush_range(ptr, ptr + step * PAGE_SIZE);
- vunmap(ptr);
- } else {
- int k;
- /* Very, very, very slow path */
-
- for (k = j; k < j + step; k++) {
- ptr = kmap_atomic(pages[k]);
- memset(ptr, 0, PAGE_SIZE);
- dmac_flush_range(ptr, ptr + PAGE_SIZE);
- kunmap_atomic(ptr);
- }
- /* scale down the step size to avoid this path */
- if (step > 1)
- step >>= 1;
- }
- }
-
KGSL_STATS_ADD(memdesc->size, &kgsl_driver.stats.page_alloc,
&kgsl_driver.stats.page_alloc_max);
+ /*
+ * Zero out the pages.
+ */
+ kgsl_zero_pages(pages, pcount);
+
done:
if (ret) {
- unsigned int count = 1;
- for (j = 0; j < pcount; j += count) {
- count = 1 << compound_order(pages[j]);
- __free_pages(pages[j], compound_order(pages[j]));
+ if (pages) {
+ unsigned int count = 1;
+
+ for (j = 0; j < pcount; j += count) {
+ count = 1 << compound_order(pages[j]);
+ kgsl_pool_free_page(pages[j]);
+ }
}
kfree(memdesc->sgt);
@@ -918,8 +901,8 @@ kgsl_sharedmem_readl(const struct kgsl_memdesc *memdesc,
if (offsetbytes % sizeof(uint32_t) != 0)
return -EINVAL;
- WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size);
- if (offsetbytes + sizeof(uint32_t) > memdesc->size)
+ WARN_ON(offsetbytes > (memdesc->size - sizeof(uint32_t)));
+ if (offsetbytes > (memdesc->size - sizeof(uint32_t)))
return -ERANGE;
rmb();
@@ -941,8 +924,8 @@ kgsl_sharedmem_writel(struct kgsl_device *device,
if (offsetbytes % sizeof(uint32_t) != 0)
return -EINVAL;
- WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size);
- if (offsetbytes + sizeof(uint32_t) > memdesc->size)
+ WARN_ON(offsetbytes > (memdesc->size - sizeof(uint32_t)));
+ if (offsetbytes > (memdesc->size - sizeof(uint32_t)))
return -ERANGE;
kgsl_cffdump_write(device,
memdesc->gpuaddr + offsetbytes,
@@ -967,8 +950,8 @@ kgsl_sharedmem_readq(const struct kgsl_memdesc *memdesc,
if (offsetbytes % sizeof(uint32_t) != 0)
return -EINVAL;
- WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size);
- if (offsetbytes + sizeof(uint32_t) > memdesc->size)
+ WARN_ON(offsetbytes > (memdesc->size - sizeof(uint32_t)));
+ if (offsetbytes > (memdesc->size - sizeof(uint32_t)))
return -ERANGE;
/*
@@ -994,8 +977,8 @@ kgsl_sharedmem_writeq(struct kgsl_device *device,
if (offsetbytes % sizeof(uint32_t) != 0)
return -EINVAL;
- WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size);
- if (offsetbytes + sizeof(uint32_t) > memdesc->size)
+ WARN_ON(offsetbytes > (memdesc->size - sizeof(uint32_t)));
+ if (offsetbytes > (memdesc->size - sizeof(uint32_t)))
return -ERANGE;
kgsl_cffdump_write(device,
lower_32_bits(memdesc->gpuaddr + offsetbytes), src);
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index dece6cbb9441..6772868d1c9b 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1143,6 +1143,30 @@ static inline int iommu_debug_init_tests(void) { return 0; }
static inline void iommu_debug_destroy_tests(void) { }
#endif
+/*
+ * This isn't really a "driver", we just need something in the device tree
+ * so that our tests can run without any client drivers, and our tests rely
+ * on parsing the device tree for nodes with the `iommus' property.
+ */
+static int iommu_debug_pass(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct of_device_id iommu_debug_of_match[] = {
+ { .compatible = "iommu-debug-test" },
+ { },
+};
+
+static struct platform_driver iommu_debug_driver = {
+ .probe = iommu_debug_pass,
+ .remove = iommu_debug_pass,
+ .driver = {
+ .name = "iommu-debug",
+ .of_match_table = iommu_debug_of_match,
+ },
+};
+
static int iommu_debug_init(void)
{
if (iommu_debug_init_tracking())
@@ -1151,11 +1175,12 @@ static int iommu_debug_init(void)
if (iommu_debug_init_tests())
return -ENODEV;
- return 0;
+ return platform_driver_register(&iommu_debug_driver);
}
static void iommu_debug_exit(void)
{
+ platform_driver_unregister(&iommu_debug_driver);
iommu_debug_destroy_tracking();
iommu_debug_destroy_tests();
}
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 305f110447a3..53f9b902e695 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -55,5 +55,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o
obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o
obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o
-obj-$(CONFIG_MSM_IRQ) += irq-msm.o
obj-$(CONFIG_MSM_SHOW_RESUME_IRQ) += msm_show_resume_irq.o
diff --git a/drivers/irqchip/irq-msm.c b/drivers/irqchip/irq-msm.c
deleted file mode 100644
index 31597484df53..000000000000
--- a/drivers/irqchip/irq-msm.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/irqchip.h>
-#include <linux/irqchip/msm-gpio-irq.h>
-#include <linux/irqchip/msm-mpm-irq.h>
-
-static int __init irq_msm_gpio_init(struct device_node *node,
- struct device_node *parent)
-{
- int rc;
-
-#ifdef CONFIG_USE_PINCTRL_IRQ
- rc = msm_tlmm_of_irq_init(node, parent);
-#else
- rc = msm_gpio_of_init(node, parent);
-#endif
- if (rc) {
- pr_err("Couldn't initlialize gpio irq rc = %d\n", rc);
- return rc;
- }
-
- /*
- * Initialize the mpm after gpio (and gic) are initialized. Note that
- * gpio irq controller is the child of gic irq controller, hence gic's
- * init function will be called prior to gpio.
- */
- of_mpm_init();
-
- return 0;
-}
-
-static int __init pinctrl_irq_dummy(struct device_node *node,
- struct device_node *parent)
-{
- /*
- * Initialize the mpm after gpio (and gic) are initialized. Note that
- * gpio irq controller is the child of gic irq controller, hence gic's
- * init function will be called prior to gpio.
- */
- of_mpm_init();
- return 0;
-}
-#ifdef CONFIG_USE_PINCTRL_IRQ
-IRQCHIP_DECLARE(tlmmv3_irq, "qcom,msm-tlmm-gp", irq_msm_gpio_init);
-#else
-IRQCHIP_DECLARE(tlmm_irq, "qcom,msm-gpio", irq_msm_gpio_init);
-#endif
-IRQCHIP_DECLARE(8996_pinctrl, "qcom,msm8996-pinctrl", pinctrl_irq_dummy);
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
index 2f84ff95a38a..57e389b4c497 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
@@ -1075,6 +1075,30 @@ static int msm_jpegdma_s_parm(struct file *file, void *fh,
return 0;
}
+/*
+ * msm_fd_g_ctrl - V4l2 ioctl get control.
+ * @file: Pointer to file struct.
+ * @fh: V4l2 File handle.
+ * @sub: Pointer to v4l2_control struct need to be filled.
+ */
+static int msm_jpegdma_g_ctrl(struct file *file, void *fh,
+ struct v4l2_control *a)
+{
+ struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh);
+
+ switch (a->id) {
+ case V4L2_CID_JPEG_DMA_MAX_DOWN_SCALE:
+ a->value = msm_jpegdma_hw_get_max_downscale(ctx->jdma_device);
+ if (a->value < 0)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/* V4l2 ioctl handlers */
static const struct v4l2_ioctl_ops fd_ioctl_ops = {
.vidioc_querycap = msm_jpegdma_querycap,
@@ -1096,6 +1120,7 @@ static const struct v4l2_ioctl_ops fd_ioctl_ops = {
.vidioc_s_crop = msm_jpegdma_s_crop,
.vidioc_g_parm = msm_jpegdma_g_parm,
.vidioc_s_parm = msm_jpegdma_s_parm,
+ .vidioc_g_ctrl = msm_jpegdma_g_ctrl,
};
/*
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c
index e994ce1b8b32..0a871c342fb4 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c
@@ -1366,6 +1366,25 @@ int msm_jpegdma_hw_get_mem_resources(struct platform_device *pdev,
}
/*
+ * msm_jpegdma_hw_get_max_downscale - Get max downscale factor from dtsi.
+ * @dma: Pointer to dma device.
+ */
+int msm_jpegdma_hw_get_max_downscale(struct msm_jpegdma_device *dma)
+{
+ int ret;
+ int max_ds_factor;
+
+ ret = of_property_read_u32(dma->dev->of_node,
+ "qcom,max-ds-factor", &max_ds_factor);
+ if (ret < 0) {
+ dev_err(dma->dev, "cannot read qcom,max-ds-factor from dtsi\n");
+ return ret;
+ }
+ dev_dbg(dma->dev, "max_ds_factor is %d\n", max_ds_factor);
+ return max_ds_factor;
+}
+
+/*
* msm_jpegdma_hw_get_qos - Get dma qos settings from device-tree.
* @dma: Pointer to dma device.
*/
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.h b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.h
index b7ff3b53aeb0..a29f3323500d 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -52,6 +52,8 @@ int msm_jpegdma_hw_get_clocks(struct msm_jpegdma_device *dma);
int msm_jpegdma_hw_put_clocks(struct msm_jpegdma_device *dma);
+int msm_jpegdma_hw_get_max_downscale(struct msm_jpegdma_device *dma);
+
int msm_jpegdma_hw_get_qos(struct msm_jpegdma_device *dma);
void msm_jpegdma_hw_put_qos(struct msm_jpegdma_device *dma);
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index e6eb22a60d3a..99f29bd0556f 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -2541,6 +2541,8 @@ static int msm_cpp_validate_input(unsigned int cmd, void *arg,
{
switch (cmd) {
case MSM_SD_SHUTDOWN:
+ case MSM_SD_NOTIFY_FREEZE:
+ case MSM_SD_UNNOTIFY_FREEZE:
break;
default: {
if (ioctl_ptr == NULL) {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_hwreg.h
index 169f6b5f130a..c1102c866ccf 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_hwreg.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_hwreg.h
@@ -63,7 +63,7 @@ struct csiphy_reg_3ph_parms_t csiphy_v5_0_3ph = {
{0x180, 0x0},
{0x184, 0x7F},
{0x1cc, 0x41},
- {0x81c, 0x1},
+ {0x81c, 0x2},
{0x82c, 0xFF},
{0x830, 0xFF},
{0x834, 0xFB},
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
index d690200b3c57..c9912f979b0a 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
@@ -633,10 +633,12 @@ static int msm_csiphy_2phase_lane_config_v50(
mipi_csiphy_2ph_lnn_cfg5.data,
csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
mipi_csiphy_2ph_lnn_cfg5.addr + offset);
- msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
- mipi_csiphy_2ph_lnck_ctrl10.data,
- csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
- mipi_csiphy_2ph_lnck_ctrl10.addr);
+ if (clk_lane == 1)
+ msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+ mipi_csiphy_2ph_lnck_ctrl10.data,
+ csiphybase +
+ csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+ mipi_csiphy_2ph_lnck_ctrl10.addr);
msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
mipi_csiphy_2ph_lnn_ctrl15.data,
csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
@@ -649,14 +651,14 @@ static int msm_csiphy_2phase_lane_config_v50(
mipi_csiphy_2ph_lnn_cfg1.data,
csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
mipi_csiphy_2ph_lnn_cfg1.addr + offset);
- msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
- mipi_csiphy_2ph_lnn_cfg2.data,
+ msm_camera_io_w((csiphy_params->settle_cnt & 0xFF),
csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
mipi_csiphy_2ph_lnn_cfg2.addr + offset);
- msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
- mipi_csiphy_2ph_lnck_ctrl3.data,
- csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
- mipi_csiphy_2ph_lnck_ctrl3.addr);
+ if (clk_lane == 1)
+ msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+ mipi_csiphy_2ph_lnck_ctrl3.data, csiphybase +
+ csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+ mipi_csiphy_2ph_lnck_ctrl3.addr);
msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
mipi_csiphy_2ph_lnn_cfg4.data, csiphybase +
csiphy_dev->ctrl_reg->csiphy_3ph_reg.
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
index 7315327e6d12..4a31b93ec37f 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
@@ -78,6 +78,7 @@ int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = client->addr_type;
cci_ctrl.cfg.cci_i2c_read_cfg.data = buf;
cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = num_byte;
+ cci_ctrl.status = -EFAULT;
rc = v4l2_subdev_call(client->cci_client->cci_subdev,
core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
CDBG("%s line %d rc = %d\n", __func__, __LINE__, rc);
@@ -168,6 +169,7 @@ int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
cci_ctrl.cfg.cci_i2c_write_cfg.data_type = MSM_CAMERA_I2C_BYTE_DATA;
cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = client->addr_type;
cci_ctrl.cfg.cci_i2c_write_cfg.size = num_byte;
+ cci_ctrl.status = -EFAULT;
rc = v4l2_subdev_call(client->cci_client->cci_subdev,
core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
CDBG("%s line %d rc = %d\n", __func__, __LINE__, rc);
@@ -382,7 +384,7 @@ int32_t msm_camera_cci_i2c_poll(struct msm_camera_i2c_client *client,
uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type, uint32_t delay_ms)
{
- int32_t rc;
+ int32_t rc = -EFAULT;
int32_t i = 0;
S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n",
__func__, addr, data, data_type);
@@ -415,7 +417,7 @@ static int32_t msm_camera_cci_i2c_set_mask(struct msm_camera_i2c_client *client,
uint32_t addr, uint16_t mask,
enum msm_camera_i2c_data_type data_type, uint16_t set_mask)
{
- int32_t rc;
+ int32_t rc = -EFAULT;
uint16_t reg_data;
rc = msm_camera_cci_i2c_read(client, addr, &reg_data, data_type);
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 1504356e685f..5216fd9c7b4a 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -2076,6 +2076,14 @@ int create_pkt_cmd_session_set_property(
pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
break;
}
+ case HAL_PARAM_VENC_CONSTRAINED_INTRA_PRED:
+ {
+ create_pkt_enable(pkt->rg_property_data,
+ HFI_PROPERTY_PARAM_VENC_CONSTRAINED_INTRA_PRED,
+ ((struct hal_enable *)pdata)->enable);
+ pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
+ break;
+ }
/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
case HAL_CONFIG_BUFFER_REQUIREMENTS:
case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 09bd865f3463..8c0df7ce08e1 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -2636,10 +2636,33 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
}
case V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE: {
struct v4l2_ctrl *air_mbs, *air_ref, *cir_mbs;
+ bool is_cont_intra_supported = false;
+
air_mbs = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS);
air_ref = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_AIR_REF);
cir_mbs = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_CIR_MBS);
+ is_cont_intra_supported =
+ (inst->fmts[CAPTURE_PORT]->fourcc == V4L2_PIX_FMT_H264) ||
+ (inst->fmts[CAPTURE_PORT]->fourcc == V4L2_PIX_FMT_HEVC);
+
+ if (is_cont_intra_supported) {
+ if (air_mbs || air_ref || cir_mbs)
+ enable.enable = true;
+ else
+ enable.enable = false;
+
+ rc = call_hfi_op(hdev, session_set_property,
+ (void *)inst->session,
+ HAL_PARAM_VENC_CONSTRAINED_INTRA_PRED, &enable);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to set constrained intra\n");
+ rc = -EINVAL;
+ break;
+ }
+ }
+
property_id = HAL_PARAM_VENC_INTRA_REFRESH;
intra_refresh.mode = ctrl->val;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index bd33a95aad20..561c6c39358d 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1051,6 +1051,7 @@ static inline int vb2_bufq_init(struct msm_vidc_inst *inst,
q->ops = msm_venc_get_vb2q_ops();
q->mem_ops = &msm_vidc_vb2_mem_ops;
q->drv_priv = inst;
+ q->allow_zero_bytesused = 1;
return vb2_queue_init(q);
}
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 56f6f6152845..dcaf9ce8d1bb 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -232,6 +232,7 @@ enum hal_property {
HAL_PARAM_VENC_BITRATE_TYPE,
HAL_PARAM_VENC_H264_PIC_ORDER_CNT,
HAL_PARAM_VENC_LOW_LATENCY,
+ HAL_PARAM_VENC_CONSTRAINED_INTRA_PRED,
};
enum hal_domain {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 385f99fe530d..04f006c50f27 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -369,6 +369,8 @@ struct hfi_buffer_info {
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x028)
#define HFI_PROPERTY_PARAM_VENC_VPX_ERROR_RESILIENCE_MODE \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x029)
+#define HFI_PROPERTY_PARAM_VENC_CONSTRAINED_INTRA_PRED \
+ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x02B)
#define HFI_PROPERTY_PARAM_VENC_HIER_B_MAX_NUM_ENH_LAYER \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x02C)
#define HFI_PROPERTY_PARAM_VENC_HIER_P_HYBRID_MODE \
diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c
index c100c47d7641..5432ce83c9a2 100644
--- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c
+++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -164,7 +164,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd,
pr_debug("%s: dec buf size: %d, num_buf: %d, enc buf size: %d, num_buf: %d\n",
__func__, effects->config.output.buf_size,
- effects->config.output.buf_size,
+ effects->config.output.num_buf,
effects->config.input.buf_size,
effects->config.input.num_buf);
rc = q6asm_audio_client_buf_alloc_contiguous(IN, effects->ac,
@@ -252,7 +252,8 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd,
bufptr = q6asm_is_cpu_buf_avail(IN, effects->ac, &size, &idx);
if (bufptr) {
- if (copy_from_user(bufptr, (void *)arg,
+ if ((effects->config.buf_cfg.output_len > size) ||
+ copy_from_user(bufptr, (void *)arg,
effects->config.buf_cfg.output_len)) {
rc = -EFAULT;
goto ioctl_fail;
@@ -308,7 +309,8 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd,
rc = -EFAULT;
goto ioctl_fail;
}
- if (copy_to_user((void *)arg, bufptr,
+ if ((effects->config.buf_cfg.input_len > size) ||
+ copy_to_user((void *)arg, bufptr,
effects->config.buf_cfg.input_len)) {
rc = -EFAULT;
goto ioctl_fail;
diff --git a/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c b/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
index c388925f4679..521bdafab76f 100644
--- a/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
@@ -23,49 +23,37 @@
#include <linux/types.h>
#include <linux/ipv6.h>
#include <net/addrconf.h>
-#include <linux/ipc_logging.h>
#include <linux/ipa.h>
#include <linux/cdev.h>
#include <linux/ipa_odu_bridge.h>
+#include "../ipa_common_i.h"
#define ODU_BRIDGE_DRV_NAME "odu_ipa_bridge"
-#define ODU_IPC_LOG_PAGES 10
-#define ODU_IPC_LOG(buf, fmt, args...) \
- ipc_log_string((buf), \
- ODU_BRIDGE_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
-
#define ODU_BRIDGE_DBG(fmt, args...) \
do { \
pr_debug(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, \
__func__, __LINE__, ## args); \
- if (odu_bridge_ctx) { \
- ODU_IPC_LOG(odu_bridge_ctx->logbuf, \
- fmt, ## args); \
- ODU_IPC_LOG(odu_bridge_ctx->logbuf_low, \
- fmt, ## args); \
- } \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ ODU_BRIDGE_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ ODU_BRIDGE_DRV_NAME " %s:%d " fmt, ## args); \
} while (0)
#define ODU_BRIDGE_DBG_LOW(fmt, args...) \
do { \
pr_debug(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, \
__func__, __LINE__, ## args); \
- if (odu_bridge_ctx && \
- odu_bridge_ctx->enable_low_prio_print) { \
- ODU_IPC_LOG(odu_bridge_ctx->logbuf_low, \
- fmt, ## args); \
- } \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ ODU_BRIDGE_DRV_NAME " %s:%d " fmt, ## args); \
} while (0)
#define ODU_BRIDGE_ERR(fmt, args...) \
do { \
pr_err(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, \
__func__, __LINE__, ## args); \
- if (odu_bridge_ctx) { \
- ODU_IPC_LOG(odu_bridge_ctx->logbuf, \
- fmt, ## args); \
- ODU_IPC_LOG(odu_bridge_ctx->logbuf_low, \
- fmt, ## args); \
- } \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ ODU_BRIDGE_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ ODU_BRIDGE_DRV_NAME " %s:%d " fmt, ## args); \
} while (0)
#define ODU_BRIDGE_FUNC_ENTRY() \
@@ -158,7 +146,6 @@ struct odu_bridge_ctx {
u32 ipa_sys_desc_size;
void *logbuf;
void *logbuf_low;
- u32 enable_low_prio_print;
};
static struct odu_bridge_ctx *odu_bridge_ctx;
@@ -683,7 +670,6 @@ static long compat_odu_bridge_ioctl(struct file *file,
static struct dentry *dent;
static struct dentry *dfile_stats;
static struct dentry *dfile_mode;
-static struct dentry *dfile_low_prio;
static ssize_t odu_debugfs_stats(struct file *file,
char __user *ubuf,
@@ -806,15 +792,6 @@ static void odu_debugfs_init(void)
goto fail;
}
- dfile_low_prio = debugfs_create_u32("enable_low_prio_print",
- read_write_mode,
- dent, &odu_bridge_ctx->enable_low_prio_print);
- if (!dfile_low_prio) {
- ODU_BRIDGE_ERR("could not create enable_low_prio_print file\n");
- goto fail;
- }
-
- return;
fail:
debugfs_remove_recursive(dent);
}
@@ -1104,34 +1081,6 @@ static void odu_bridge_deregister_properties(void)
ODU_BRIDGE_FUNC_EXIT();
}
-static int odu_bridge_ipc_logging_init(void)
-{
- int result;
-
- odu_bridge_ctx->logbuf = ipc_log_context_create(ODU_IPC_LOG_PAGES,
- "ipa_odu_bridge", 0);
- if (odu_bridge_ctx->logbuf == NULL) {
- /* we can't use odu_bridge print macros on failures */
- pr_err("odu_bridge: failed to get logbuf\n");
- return -ENOMEM;
- }
-
- odu_bridge_ctx->logbuf_low =
- ipc_log_context_create(ODU_IPC_LOG_PAGES,
- "ipa_odu_bridge_low", 0);
- if (odu_bridge_ctx->logbuf_low == NULL) {
- pr_err("odu_bridge: failed to get logbuf_low\n");
- result = -ENOMEM;
- goto fail_logbuf_low;
- }
-
- return 0;
-
-fail_logbuf_low:
- ipc_log_context_destroy(odu_bridge_ctx->logbuf);
- return result;
-}
-
/**
* odu_bridge_init() - Initialize the ODU bridge driver
* @params: initialization parameters
@@ -1183,13 +1132,6 @@ int odu_bridge_init(struct odu_bridge_params *params)
return -ENOMEM;
}
- res = odu_bridge_ipc_logging_init();
- if (res) {
- /* ODU_BRIDGE_ERR will crash on NULL if we use it here*/
- pr_err("odu_bridge: failed to initialize ipc logging\n");
- res = -EFAULT;
- goto fail_ipc_create;
- }
odu_bridge_ctx->class = class_create(THIS_MODULE, ODU_BRIDGE_DRV_NAME);
if (!odu_bridge_ctx->class) {
ODU_BRIDGE_ERR("Class_create err.\n");
@@ -1264,9 +1206,6 @@ fail_device_create:
fail_alloc_chrdev_region:
class_destroy(odu_bridge_ctx->class);
fail_class_create:
- ipc_log_context_destroy(odu_bridge_ctx->logbuf);
- ipc_log_context_destroy(odu_bridge_ctx->logbuf_low);
-fail_ipc_create:
kfree(odu_bridge_ctx);
odu_bridge_ctx = NULL;
return res;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index 06f8ab6e3e94..feb6225470ab 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -3473,6 +3473,7 @@ static int apps_cons_request_resource(void)
static void ipa_sps_release_resource(struct work_struct *work)
{
+ mutex_lock(&ipa_ctx->sps_pm.sps_pm_lock);
/* check whether still need to decrease client usage */
if (atomic_read(&ipa_ctx->sps_pm.dec_clients)) {
if (atomic_read(&ipa_ctx->sps_pm.eot_activity)) {
@@ -3484,6 +3485,7 @@ static void ipa_sps_release_resource(struct work_struct *work)
}
}
atomic_set(&ipa_ctx->sps_pm.eot_activity, 0);
+ mutex_unlock(&ipa_ctx->sps_pm.sps_pm_lock);
}
int ipa_create_apps_resource(void)
@@ -3946,6 +3948,9 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p,
wakeup_source_init(&ipa_ctx->w_lock, "IPA_WS");
spin_lock_init(&ipa_ctx->wakelock_ref_cnt.spinlock);
+ /* Initialize the SPS PM lock. */
+ mutex_init(&ipa_ctx->sps_pm.sps_pm_lock);
+
/* Initialize IPA RM (resource manager) */
result = ipa_rm_initialize();
if (result) {
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
index 35157f961231..2255a74331cb 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
@@ -497,7 +497,7 @@ int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
}
} else {
tx_pkt->mem.base = desc[i].frag;
- tx_pkt->mem.size = skb_frag_size(desc[i].frag);
+ tx_pkt->mem.size = desc[i].len;
if (!desc[i].dma_address_valid) {
tx_pkt->mem.phys_base =
@@ -815,6 +815,11 @@ static void ipa_rx_switch_to_intr_mode(struct ipa_sys_context *sys)
{
int ret;
+ if (!sys->ep || !sys->ep->valid) {
+ IPAERR("EP Not Valid, no need to cleanup.\n");
+ return;
+ }
+
if (!atomic_read(&sys->curr_polling_state)) {
IPAERR("already in intr mode\n");
goto fail;
@@ -1427,8 +1432,11 @@ int ipa2_teardown_sys_pipe(u32 clnt_hdl)
} while (1);
}
- if (IPA_CLIENT_IS_CONS(ep->client))
+ if (IPA_CLIENT_IS_CONS(ep->client)) {
cancel_delayed_work_sync(&ep->sys->replenish_rx_work);
+ cancel_delayed_work_sync(&ep->sys->switch_to_intr_work);
+ }
+
flush_workqueue(ep->sys->wq);
sps_disconnect(ep->ep_hdl);
dma_free_coherent(ipa_ctx->pdev, ep->connect.desc.size,
@@ -1626,6 +1634,7 @@ int ipa2_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
for (f = 0; f < num_frags; f++) {
desc[2+f].frag = &skb_shinfo(skb)->frags[f];
desc[2+f].type = IPA_DATA_DESC_SKB_PAGED;
+ desc[2+f].len = skb_frag_size(desc[2+f].frag);
}
/* don't free skb till frag mappings are released */
@@ -1665,6 +1674,7 @@ int ipa2_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
for (f = 0; f < num_frags; f++) {
desc[1+f].frag = &skb_shinfo(skb)->frags[f];
desc[1+f].type = IPA_DATA_DESC_SKB_PAGED;
+ desc[1+f].len = skb_frag_size(desc[1+f].frag);
}
/* don't free skb till frag mappings are released */
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index ce2ffc8f1cee..7d5daf202112 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -1111,10 +1111,12 @@ struct ipa_uc_wdi_ctx {
* @dec_clients: true if need to decrease active clients count
* @eot_activity: represent EOT interrupt activity to determine to reset
* the inactivity timer
+ * @sps_pm_lock: Lock to protect the sps_pm functionality.
*/
struct ipa_sps_pm {
atomic_t dec_clients;
atomic_t eot_activity;
+ struct mutex sps_pm_lock;
};
/**
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c
index 70e0db98e948..00f18333587b 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c
@@ -46,7 +46,6 @@ static struct workqueue_struct *ipa_clnt_req_workqueue;
static struct workqueue_struct *ipa_clnt_resp_workqueue;
static void *curr_conn;
static bool qmi_modem_init_fin, qmi_indication_fin;
-static struct work_struct ipa_qmi_service_init_work;
static uint32_t ipa_wan_platform;
struct ipa_qmi_context *ipa_qmi_ctx;
static bool first_time_handshake;
@@ -855,11 +854,6 @@ static int ipa_q6_clnt_svc_event_notify(struct notifier_block *this,
queue_delayed_work(ipa_clnt_req_workqueue,
&work_svc_arrive, 0);
break;
- case QMI_SERVER_EXIT:
- if (!atomic_read(&workqueues_stopped))
- queue_delayed_work(ipa_clnt_req_workqueue,
- &work_svc_exit, 0);
- break;
default:
break;
}
@@ -871,7 +865,7 @@ static struct notifier_block ipa_q6_clnt_nb = {
.notifier_call = ipa_q6_clnt_svc_event_notify,
};
-static void ipa_qmi_service_init_worker(struct work_struct *work)
+static void ipa_qmi_service_init_worker(void)
{
int rc;
@@ -968,9 +962,7 @@ int ipa_qmi_service_init(uint32_t wan_platform_type)
atomic_set(&workqueues_stopped, 0);
if (0 == atomic_read(&ipa_qmi_initialized)) {
- INIT_WORK(&ipa_qmi_service_init_work,
- ipa_qmi_service_init_worker);
- schedule_work(&ipa_qmi_service_init_work);
+ ipa_qmi_service_init_worker();
}
return 0;
}
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
index 449e9a1890b2..9d4704ded0c3 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -660,7 +660,9 @@ static int ipa_generate_rt_hw_tbl_v2(enum ipa_ip_type ip,
return 0;
proc_err:
- dma_free_coherent(ipa_ctx->pdev, mem->size, mem->base, mem->phys_base);
+ if (mem->size)
+ dma_free_coherent(ipa_ctx->pdev, mem->size, mem->base,
+ mem->phys_base);
base_err:
dma_free_coherent(ipa_ctx->pdev, head->size, head->base,
head->phys_base);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c
index b49815b24bc2..d529622f1e19 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c
@@ -17,7 +17,9 @@
#define IPA_PKT_FLUSH_TO_US 100
#define IPA_UC_POLL_SLEEP_USEC 100
#define IPA_UC_POLL_MAX_RETRY 10000
+#define HOLB_WORKQUEUE_NAME "ipa_holb_wq"
+static struct workqueue_struct *ipa_holb_wq;
static void ipa_start_monitor_holb(struct work_struct *work);
static DECLARE_WORK(ipa_holb_work, ipa_start_monitor_holb);
@@ -470,7 +472,7 @@ static void ipa_uc_response_hdlr(enum ipa_irq_type interrupt,
* pipe if valid.
*/
if (ipa_ctx->ipa_hw_type == IPA_HW_v2_6L)
- queue_work(ipa_ctx->power_mgmt_wq, &ipa_holb_work);
+ queue_work(ipa_holb_wq, &ipa_holb_work);
} else if (ipa_ctx->uc_ctx.uc_sram_mmio->responseOp ==
IPA_HW_2_CPU_RESPONSE_CMD_COMPLETED) {
uc_rsp.raw32b = ipa_ctx->uc_ctx.uc_sram_mmio->responseParams;
@@ -508,6 +510,13 @@ int ipa_uc_interface_init(void)
return 0;
}
+ ipa_holb_wq = create_singlethread_workqueue(
+ HOLB_WORKQUEUE_NAME);
+ if (!ipa_holb_wq) {
+ IPAERR("HOLB workqueue creation failed\n");
+ return -ENOMEM;
+ }
+
mutex_init(&ipa_ctx->uc_ctx.uc_lock);
if (ipa_ctx->ipa_hw_type >= IPA_HW_v2_5) {
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index 672568468c47..6fd9b4e61e02 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -662,11 +662,14 @@ int ipa2_resume_resource(enum ipa_rm_resource_name resource)
IPADBG("%d will be resumed on connect.\n", client);
if (ipa_ctx->ep[ipa_ep_idx].client == client &&
ipa_should_pipe_be_suspended(client)) {
- if (ipa_ctx->ep[ipa_ep_idx].valid) {
+ spin_lock(&ipa_ctx->disconnect_lock);
+ if (ipa_ctx->ep[ipa_ep_idx].valid &&
+ !ipa_ctx->ep[ipa_ep_idx].disconnect_in_progress) {
memset(&suspend, 0, sizeof(suspend));
suspend.ipa_ep_suspend = false;
ipa2_cfg_ep_ctrl(ipa_ep_idx, &suspend);
}
+ spin_unlock(&ipa_ctx->disconnect_lock);
}
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c
index 966f279d863b..9d1ff18d7ed0 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dma.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -33,16 +33,38 @@
#define IPADMA_DRV_NAME "ipa_dma"
#define IPADMA_DBG(fmt, args...) \
- pr_debug(IPADMA_DRV_NAME " %s:%d " fmt, \
- __func__, __LINE__, ## args)
+ do { \
+ pr_debug(IPADMA_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPADMA_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPADMA_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+#define IPADMA_DBG_LOW(fmt, args...) \
+ do { \
+ pr_debug(IPADMA_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPADMA_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
#define IPADMA_ERR(fmt, args...) \
- pr_err(IPADMA_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+ do { \
+ pr_err(IPADMA_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPADMA_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPADMA_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
#define IPADMA_FUNC_ENTRY() \
- IPADMA_DBG("ENTRY\n")
+ IPADMA_DBG_LOW("ENTRY\n")
#define IPADMA_FUNC_EXIT() \
- IPADMA_DBG("EXIT\n")
+ IPADMA_DBG_LOW("EXIT\n")
#ifdef CONFIG_DEBUG_FS
#define IPADMA_MAX_MSG_LEN 1024
@@ -255,7 +277,7 @@ int ipa3_dma_enable(void)
}
mutex_lock(&ipa3_dma_ctx->enable_lock);
if (ipa3_dma_ctx->is_enabled) {
- IPADMA_DBG("Already enabled.\n");
+ IPADMA_ERR("Already enabled.\n");
mutex_unlock(&ipa3_dma_ctx->enable_lock);
return -EPERM;
}
@@ -281,7 +303,7 @@ static bool ipa3_dma_work_pending(void)
IPADMA_DBG("pending uc\n");
return true;
}
- IPADMA_DBG("no pending work\n");
+ IPADMA_DBG_LOW("no pending work\n");
return false;
}
@@ -309,7 +331,7 @@ int ipa3_dma_disable(void)
mutex_lock(&ipa3_dma_ctx->enable_lock);
spin_lock_irqsave(&ipa3_dma_ctx->pending_lock, flags);
if (!ipa3_dma_ctx->is_enabled) {
- IPADMA_DBG("Already disabled.\n");
+ IPADMA_ERR("Already disabled.\n");
spin_unlock_irqrestore(&ipa3_dma_ctx->pending_lock, flags);
mutex_unlock(&ipa3_dma_ctx->enable_lock);
return -EPERM;
@@ -358,7 +380,7 @@ int ipa3_dma_sync_memcpy(u64 dest, u64 src, int len)
bool stop_polling = false;
IPADMA_FUNC_ENTRY();
- IPADMA_DBG("input parameters: dest = 0x%llx, src = 0x%llx, len = %d\n",
+ IPADMA_DBG_LOW("dest = 0x%llx, src = 0x%llx, len = %d\n",
dest, src, len);
if (ipa3_dma_ctx == NULL) {
IPADMA_ERR("IPADMA isn't initialized, can't memcpy\n");
@@ -390,7 +412,7 @@ int ipa3_dma_sync_memcpy(u64 dest, u64 src, int len)
if (atomic_read(&ipa3_dma_ctx->sync_memcpy_pending_cnt) >=
IPA_DMA_MAX_PENDING_SYNC) {
atomic_dec(&ipa3_dma_ctx->sync_memcpy_pending_cnt);
- IPADMA_DBG("Reached pending requests limit\n");
+ IPADMA_ERR("Reached pending requests limit\n");
return -EFAULT;
}
}
@@ -575,7 +597,7 @@ int ipa3_dma_async_memcpy(u64 dest, u64 src, int len,
unsigned long flags;
IPADMA_FUNC_ENTRY();
- IPADMA_DBG("input parameters: dest = 0x%llx, src = 0x%llx, len = %d\n",
+ IPADMA_DBG_LOW("dest = 0x%llx, src = 0x%llx, len = %d\n",
dest, src, len);
if (ipa3_dma_ctx == NULL) {
IPADMA_ERR("IPADMA isn't initialized, can't memcpy\n");
@@ -612,7 +634,7 @@ int ipa3_dma_async_memcpy(u64 dest, u64 src, int len,
if (atomic_read(&ipa3_dma_ctx->async_memcpy_pending_cnt) >=
IPA_DMA_MAX_PENDING_ASYNC) {
atomic_dec(&ipa3_dma_ctx->async_memcpy_pending_cnt);
- IPADMA_DBG("Reached pending requests limit\n");
+ IPADMA_ERR("Reached pending requests limit\n");
return -EFAULT;
}
}
@@ -774,7 +796,7 @@ void ipa3_dma_destroy(void)
IPADMA_FUNC_ENTRY();
if (!ipa3_dma_ctx) {
- IPADMA_DBG("IPADMA isn't initialized\n");
+ IPADMA_ERR("IPADMA isn't initialized\n");
return;
}
@@ -919,7 +941,7 @@ static ssize_t ipa3_dma_debugfs_reset_statistics(struct file *file,
switch (in_num) {
case 0:
if (ipa3_dma_work_pending())
- IPADMA_DBG("Note, there are pending memcpy\n");
+ IPADMA_ERR("Note, there are pending memcpy\n");
atomic_set(&ipa3_dma_ctx->total_async_memcpy, 0);
atomic_set(&ipa3_dma_ctx->total_sync_memcpy, 0);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index f58751d4c0d3..f0f79d066f0b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
@@ -22,12 +22,6 @@ static const u32 ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN_MAX] = { 32, 64};
#define HDR_PROC_TYPE_IS_VALID(type) \
((type) >= 0 && (type) < IPA_HDR_PROC_MAX)
-/* uCP command numbers */
-#define IPA_HDR_UCP_802_3_TO_802_3 6
-#define IPA_HDR_UCP_802_3_TO_ETHII 7
-#define IPA_HDR_UCP_ETHII_TO_802_3 8
-#define IPA_HDR_UCP_ETHII_TO_ETHII 9
-
/**
* ipa3_generate_hdr_hw_tbl() - generates the headers table
* @mem: [out] buffer to put the header table
@@ -60,70 +54,36 @@ static int ipa3_generate_hdr_hw_tbl(struct ipa3_mem_buffer *mem)
continue;
IPADBG_LOW("hdr of len %d ofst=%d\n", entry->hdr_len,
entry->offset_entry->offset);
- memcpy(mem->base + entry->offset_entry->offset, entry->hdr,
- entry->hdr_len);
+ ipahal_cp_hdr_to_hw_buff(mem->base, entry->offset_entry->offset,
+ entry->hdr, entry->hdr_len);
}
return 0;
}
-static void ipa3_hdr_proc_ctx_to_hw_format(struct ipa3_mem_buffer *mem,
+static int ipa3_hdr_proc_ctx_to_hw_format(struct ipa3_mem_buffer *mem,
u32 hdr_base_addr)
{
struct ipa3_hdr_proc_ctx_entry *entry;
+ int ret;
list_for_each_entry(entry,
&ipa3_ctx->hdr_proc_ctx_tbl.head_proc_ctx_entry_list,
link) {
IPADBG_LOW("processing type %d ofst=%d\n",
entry->type, entry->offset_entry->offset);
- if (entry->type == IPA_HDR_PROC_NONE) {
- struct ipa3_hdr_proc_ctx_add_hdr_seq *ctx;
-
- ctx = (struct ipa3_hdr_proc_ctx_add_hdr_seq *)
- (mem->base + entry->offset_entry->offset);
- ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
- ctx->hdr_add.tlv.length = 1;
- ctx->hdr_add.tlv.value = entry->hdr->hdr_len;
- ctx->hdr_add.hdr_addr = (entry->hdr->is_hdr_proc_ctx) ?
- entry->hdr->phys_base :
- hdr_base_addr +
- entry->hdr->offset_entry->offset;
- IPADBG_LOW("header address 0x%x\n",
- ctx->hdr_add.hdr_addr);
- ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
- ctx->end.length = 0;
- ctx->end.value = 0;
- } else {
- struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq *ctx;
-
- ctx = (struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq *)
- (mem->base + entry->offset_entry->offset);
- ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
- ctx->hdr_add.tlv.length = 1;
- ctx->hdr_add.tlv.value = entry->hdr->hdr_len;
- ctx->hdr_add.hdr_addr = (entry->hdr->is_hdr_proc_ctx) ?
- entry->hdr->phys_base :
- hdr_base_addr +
- entry->hdr->offset_entry->offset;
- IPADBG_LOW("header address 0x%x\n",
- ctx->hdr_add.hdr_addr);
- ctx->cmd.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD;
- ctx->cmd.length = 0;
- if (entry->type == IPA_HDR_PROC_ETHII_TO_ETHII)
- ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_ETHII;
- else if (entry->type == IPA_HDR_PROC_ETHII_TO_802_3)
- ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_802_3;
- else if (entry->type == IPA_HDR_PROC_802_3_TO_ETHII)
- ctx->cmd.value = IPA_HDR_UCP_802_3_TO_ETHII;
- else if (entry->type == IPA_HDR_PROC_802_3_TO_802_3)
- ctx->cmd.value = IPA_HDR_UCP_802_3_TO_802_3;
- IPADBG_LOW("command id %d\n", ctx->cmd.value);
- ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
- ctx->end.length = 0;
- ctx->end.value = 0;
- }
+ ret = ipahal_cp_proc_ctx_to_hw_buff(entry->type, mem->base,
+ entry->offset_entry->offset,
+ entry->hdr->hdr_len,
+ entry->hdr->is_hdr_proc_ctx,
+ entry->hdr->phys_base,
+ hdr_base_addr,
+ entry->hdr->offset_entry->offset);
+ if (ret)
+ return ret;
}
+
+ return 0;
}
/**
@@ -162,9 +122,7 @@ static int ipa3_generate_hdr_proc_ctx_hw_tbl(u32 hdr_sys_addr,
memset(aligned_mem->base, 0, aligned_mem->size);
hdr_base_addr = (ipa3_ctx->hdr_tbl_lcl) ? IPA_MEM_PART(apps_hdr_ofst) :
hdr_sys_addr;
- ipa3_hdr_proc_ctx_to_hw_format(aligned_mem, hdr_base_addr);
-
- return 0;
+ return ipa3_hdr_proc_ctx_to_hw_format(aligned_mem, hdr_base_addr);
}
/**
@@ -395,9 +353,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx,
hdr_entry->ref_cnt++;
entry->cookie = IPA_COOKIE;
- needed_len = (proc_ctx->type == IPA_HDR_PROC_NONE) ?
- sizeof(struct ipa3_hdr_proc_ctx_add_hdr_seq) :
- sizeof(struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq);
+ needed_len = ipahal_get_proc_ctx_needed_len(proc_ctx->type);
if (needed_len <= ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN0]) {
bin = IPA_HDR_PROC_CTX_BIN0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h
index 1b732efe2b2c..38a63f8a67ba 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h
@@ -16,11 +16,6 @@
/* This header defines various HW related data types */
-/* Processing context TLV type */
-#define IPA_PROC_CTX_TLV_TYPE_END 0
-#define IPA_PROC_CTX_TLV_TYPE_HDR_ADD 1
-#define IPA_PROC_CTX_TLV_TYPE_PROC_CMD 3
-
#define IPA_RULE_ID_INVALID 0x3FF
/**
@@ -94,40 +89,6 @@ struct ipa3_rt_rule_hw_hdr {
} u;
};
-/**
- * struct ipa3_hdr_proc_ctx_tlv -
- * HW structure of IPA processing context header - TLV part
- * @type: 0 - end type
- * 1 - header addition type
- * 3 - processing command type
- * @length: number of bytes after tlv
- * for type:
- * 0 - needs to be 0
- * 1 - header addition length
- * 3 - number of 32B including type and length.
- * @value: specific value for type
- * for type:
- * 0 - needs to be 0
- * 1 - header length
- * 3 - command ID (see IPA_HDR_UCP_* definitions)
- */
-struct ipa3_hdr_proc_ctx_tlv {
- u32 type:8;
- u32 length:8;
- u32 value:16;
-};
-
-/**
- * struct ipa3_hdr_proc_ctx_hdr_add -
- * HW structure of IPA processing context - add header tlv
- * @tlv: IPA processing context TLV
- * @hdr_addr: processing context header address
- */
-struct ipa3_hdr_proc_ctx_hdr_add {
- struct ipa3_hdr_proc_ctx_tlv tlv;
- u32 hdr_addr;
-};
-
#define IPA_A5_MUX_HDR_EXCP_FLAG_IP BIT(7)
#define IPA_A5_MUX_HDR_EXCP_FLAG_NAT BIT(6)
#define IPA_A5_MUX_HDR_EXCP_FLAG_SW_FLT BIT(5)
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index a21df09b7059..cec83ef7a202 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -396,30 +396,6 @@ struct ipa3_hdr_proc_ctx_offset_entry {
};
/**
- * struct ipa3_hdr_proc_ctx_add_hdr_seq -
- * IPA processing context header - add header sequence
- * @hdr_add: add header command
- * @end: tlv end command (cmd.type must be 0)
- */
-struct ipa3_hdr_proc_ctx_add_hdr_seq {
- struct ipa3_hdr_proc_ctx_hdr_add hdr_add;
- struct ipa3_hdr_proc_ctx_tlv end;
-};
-
-/**
- * struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq -
- * IPA processing context header - process command sequence
- * @hdr_add: add header command
- * @cmd: tlv processing command (cmd.type must be 3)
- * @end: tlv end command (cmd.type must be 0)
- */
-struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq {
- struct ipa3_hdr_proc_ctx_hdr_add hdr_add;
- struct ipa3_hdr_proc_ctx_tlv cmd;
- struct ipa3_hdr_proc_ctx_tlv end;
-};
-
-/**
struct ipa3_hdr_proc_ctx_entry - IPA processing context header table entry
* @link: entry's link in global header table entries list
* @type:
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
index 401bb0f61ee8..517093adbe81 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
@@ -21,15 +21,42 @@
#include "ipa_qmi_service.h"
#define IPA_MHI_DRV_NAME "ipa_mhi"
+
+
#define IPA_MHI_DBG(fmt, args...) \
- pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \
- __func__, __LINE__, ## args)
+ do { \
+ pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+#define IPA_MHI_DBG_LOW(fmt, args...) \
+ do { \
+ pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+
#define IPA_MHI_ERR(fmt, args...) \
- pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+ do { \
+ pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+
#define IPA_MHI_FUNC_ENTRY() \
- IPA_MHI_DBG("ENTRY\n")
+ IPA_MHI_DBG_LOW("ENTRY\n")
#define IPA_MHI_FUNC_EXIT() \
- IPA_MHI_DBG("EXIT\n")
+ IPA_MHI_DBG_LOW("EXIT\n")
#define IPA_MHI_GSI_ER_START 10
#define IPA_MHI_GSI_ER_END 16
@@ -756,12 +783,12 @@ static void ipa3_mhi_rm_prod_notify(void *user_data, enum ipa_rm_event event,
switch (event) {
case IPA_RM_RESOURCE_GRANTED:
- IPA_MHI_DBG("IPA_RM_RESOURCE_GRANTED\n");
+ IPA_MHI_DBG_LOW("IPA_RM_RESOURCE_GRANTED\n");
complete_all(&ipa3_mhi_ctx->rm_prod_granted_comp);
break;
case IPA_RM_RESOURCE_RELEASED:
- IPA_MHI_DBG("IPA_RM_RESOURCE_RELEASED\n");
+ IPA_MHI_DBG_LOW("IPA_RM_RESOURCE_RELEASED\n");
break;
default:
@@ -828,7 +855,7 @@ static int ipa3_mhi_rm_cons_request(void)
}
spin_unlock_irqrestore(&ipa3_mhi_ctx->state_lock, flags);
- IPA_MHI_DBG("EXIT with %d\n", res);
+ IPA_MHI_DBG_LOW("EXIT with %d\n", res);
return res;
}
@@ -878,7 +905,7 @@ static int ipa3_mhi_request_prod(void)
IPA_MHI_FUNC_ENTRY();
reinit_completion(&ipa3_mhi_ctx->rm_prod_granted_comp);
- IPA_MHI_DBG("requesting mhi prod\n");
+ IPA_MHI_DBG_LOW("requesting mhi prod\n");
res = ipa_rm_request_resource(IPA_RM_RESOURCE_MHI_PROD);
if (res) {
if (res != -EINPROGRESS) {
@@ -894,7 +921,7 @@ static int ipa3_mhi_request_prod(void)
}
}
- IPA_MHI_DBG("mhi prod granted\n");
+ IPA_MHI_DBG_LOW("mhi prod granted\n");
IPA_MHI_FUNC_EXIT();
return 0;
@@ -1071,11 +1098,12 @@ static bool ipa3_mhi_gsi_channel_empty(struct ipa3_mhi_channel_ctx *channel)
IPA_MHI_FUNC_ENTRY();
if (!channel->stop_in_proc) {
- IPA_MHI_DBG("Channel is not in STOP_IN_PROC\n");
+ IPA_MHI_DBG_LOW("Channel is not in STOP_IN_PROC\n");
return true;
}
- IPA_MHI_DBG("Stopping GSI channel %ld\n", channel->ep->gsi_chan_hdl);
+ IPA_MHI_DBG_LOW("Stopping GSI channel %ld\n",
+ channel->ep->gsi_chan_hdl);
res = gsi_stop_channel(channel->ep->gsi_chan_hdl);
if (res != 0 &&
res != -GSI_STATUS_AGAIN &&
@@ -1087,7 +1115,7 @@ static bool ipa3_mhi_gsi_channel_empty(struct ipa3_mhi_channel_ctx *channel)
}
if (res == 0) {
- IPA_MHI_DBG("GSI channel %ld STOP\n",
+ IPA_MHI_DBG_LOW("GSI channel %ld STOP\n",
channel->ep->gsi_chan_hdl);
channel->stop_in_proc = false;
return true;
@@ -1129,7 +1157,7 @@ static bool ipa3_mhi_wait_for_ul_empty_timeout(unsigned int msecs)
}
if (time_after(jiffies, jiffies_start + jiffies_timeout)) {
- IPA_MHI_DBG("timeout waiting for UL empty\n");
+ IPA_MHI_DBG_LOW("timeout waiting for UL empty\n");
break;
}
@@ -1441,31 +1469,31 @@ static int ipa_mhi_start_uc_channel(struct ipa3_mhi_channel_ctx *channel,
static void ipa_mhi_dump_ch_ctx(struct ipa3_mhi_channel_ctx *channel)
{
- IPA_MHI_DBG("ch_id %d\n", channel->id);
- IPA_MHI_DBG("chstate 0x%x\n", channel->ch_ctx_host.chstate);
- IPA_MHI_DBG("brstmode 0x%x\n", channel->ch_ctx_host.brstmode);
- IPA_MHI_DBG("pollcfg 0x%x\n", channel->ch_ctx_host.pollcfg);
- IPA_MHI_DBG("chtype 0x%x\n", channel->ch_ctx_host.chtype);
- IPA_MHI_DBG("erindex 0x%x\n", channel->ch_ctx_host.erindex);
- IPA_MHI_DBG("rbase 0x%llx\n", channel->ch_ctx_host.rbase);
- IPA_MHI_DBG("rlen 0x%llx\n", channel->ch_ctx_host.rlen);
- IPA_MHI_DBG("rp 0x%llx\n", channel->ch_ctx_host.rp);
- IPA_MHI_DBG("wp 0x%llx\n", channel->ch_ctx_host.wp);
+ IPA_MHI_DBG_LOW("ch_id %d\n", channel->id);
+ IPA_MHI_DBG_LOW("chstate 0x%x\n", channel->ch_ctx_host.chstate);
+ IPA_MHI_DBG_LOW("brstmode 0x%x\n", channel->ch_ctx_host.brstmode);
+ IPA_MHI_DBG_LOW("pollcfg 0x%x\n", channel->ch_ctx_host.pollcfg);
+ IPA_MHI_DBG_LOW("chtype 0x%x\n", channel->ch_ctx_host.chtype);
+ IPA_MHI_DBG_LOW("erindex 0x%x\n", channel->ch_ctx_host.erindex);
+ IPA_MHI_DBG_LOW("rbase 0x%llx\n", channel->ch_ctx_host.rbase);
+ IPA_MHI_DBG_LOW("rlen 0x%llx\n", channel->ch_ctx_host.rlen);
+ IPA_MHI_DBG_LOW("rp 0x%llx\n", channel->ch_ctx_host.rp);
+ IPA_MHI_DBG_LOW("wp 0x%llx\n", channel->ch_ctx_host.wp);
}
static void ipa_mhi_dump_ev_ctx(struct ipa3_mhi_channel_ctx *channel)
{
- IPA_MHI_DBG("ch_id %d event id %d\n", channel->id,
+ IPA_MHI_DBG_LOW("ch_id %d event id %d\n", channel->id,
channel->ch_ctx_host.erindex);
- IPA_MHI_DBG("intmodc 0x%x\n", channel->ev_ctx_host.intmodc);
- IPA_MHI_DBG("intmodt 0x%x\n", channel->ev_ctx_host.intmodt);
- IPA_MHI_DBG("ertype 0x%x\n", channel->ev_ctx_host.ertype);
- IPA_MHI_DBG("msivec 0x%x\n", channel->ev_ctx_host.msivec);
- IPA_MHI_DBG("rbase 0x%llx\n", channel->ev_ctx_host.rbase);
- IPA_MHI_DBG("rlen 0x%llx\n", channel->ev_ctx_host.rlen);
- IPA_MHI_DBG("rp 0x%llx\n", channel->ev_ctx_host.rp);
- IPA_MHI_DBG("wp 0x%llx\n", channel->ev_ctx_host.wp);
+ IPA_MHI_DBG_LOW("intmodc 0x%x\n", channel->ev_ctx_host.intmodc);
+ IPA_MHI_DBG_LOW("intmodt 0x%x\n", channel->ev_ctx_host.intmodt);
+ IPA_MHI_DBG_LOW("ertype 0x%x\n", channel->ev_ctx_host.ertype);
+ IPA_MHI_DBG_LOW("msivec 0x%x\n", channel->ev_ctx_host.msivec);
+ IPA_MHI_DBG_LOW("rbase 0x%llx\n", channel->ev_ctx_host.rbase);
+ IPA_MHI_DBG_LOW("rlen 0x%llx\n", channel->ev_ctx_host.rlen);
+ IPA_MHI_DBG_LOW("rp 0x%llx\n", channel->ev_ctx_host.rp);
+ IPA_MHI_DBG_LOW("wp 0x%llx\n", channel->ev_ctx_host.wp);
}
static int ipa_mhi_read_ch_ctx(struct ipa3_mhi_channel_ctx *channel)
@@ -2235,7 +2263,7 @@ static int ipa3_mhi_suspend_ul_channels(void)
if (ipa3_mhi_ctx->ul_channels[i].state !=
IPA_HW_MHI_CHANNEL_STATE_RUN)
continue;
- IPA_MHI_DBG("suspending channel %d\n",
+ IPA_MHI_DBG_LOW("suspending channel %d\n",
ipa3_mhi_ctx->ul_channels[i].id);
if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI)
@@ -2271,7 +2299,7 @@ static int ipa3_mhi_resume_ul_channels(bool LPTransitionRejected)
IPA_HW_MHI_CHANNEL_STATE_SUSPEND)
continue;
channel = &ipa3_mhi_ctx->ul_channels[i];
- IPA_MHI_DBG("resuming channel %d\n", channel->id);
+ IPA_MHI_DBG_LOW("resuming channel %d\n", channel->id);
if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) {
if (channel->brstmode_enabled &&
@@ -2324,7 +2352,7 @@ static int ipa3_mhi_stop_event_update_ul_channels(void)
if (ipa3_mhi_ctx->ul_channels[i].state !=
IPA_HW_MHI_CHANNEL_STATE_SUSPEND)
continue;
- IPA_MHI_DBG("stop update event channel %d\n",
+ IPA_MHI_DBG_LOW("stop update event channel %d\n",
ipa3_mhi_ctx->ul_channels[i].id);
res = ipa3_uc_mhi_stop_event_update_channel(
ipa3_mhi_ctx->ul_channels[i].index);
@@ -2351,7 +2379,7 @@ static int ipa3_mhi_suspend_dl_channels(void)
if (ipa3_mhi_ctx->dl_channels[i].state !=
IPA_HW_MHI_CHANNEL_STATE_RUN)
continue;
- IPA_MHI_DBG("suspending channel %d\n",
+ IPA_MHI_DBG_LOW("suspending channel %d\n",
ipa3_mhi_ctx->dl_channels[i].id);
if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI)
res = ipa3_mhi_suspend_gsi_channel(
@@ -2386,7 +2414,7 @@ static int ipa3_mhi_resume_dl_channels(bool LPTransitionRejected)
IPA_HW_MHI_CHANNEL_STATE_SUSPEND)
continue;
channel = &ipa3_mhi_ctx->dl_channels[i];
- IPA_MHI_DBG("resuming channel %d\n", channel->id);
+ IPA_MHI_DBG_LOW("resuming channel %d\n", channel->id);
if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) {
if (channel->brstmode_enabled &&
@@ -2437,7 +2465,7 @@ static int ipa3_mhi_stop_event_update_dl_channels(void)
if (ipa3_mhi_ctx->dl_channels[i].state !=
IPA_HW_MHI_CHANNEL_STATE_SUSPEND)
continue;
- IPA_MHI_DBG("stop update event channel %d\n",
+ IPA_MHI_DBG_LOW("stop update event channel %d\n",
ipa3_mhi_ctx->dl_channels[i].id);
res = ipa3_uc_mhi_stop_event_update_channel(
ipa3_mhi_ctx->dl_channels[i].index);
@@ -2577,7 +2605,7 @@ static bool ipa3_mhi_has_open_aggr_frame(void)
int ipa_ep_idx;
aggr_state_active = ipahal_read_reg(IPA_STATE_AGGR_ACTIVE);
- IPA_MHI_DBG("IPA_STATE_AGGR_ACTIVE_OFST 0x%x\n", aggr_state_active);
+ IPA_MHI_DBG_LOW("IPA_STATE_AGGR_ACTIVE_OFST 0x%x\n", aggr_state_active);
for (i = 0; i < IPA_MHI_MAX_DL_CHANNELS; i++) {
channel = &ipa3_mhi_ctx->dl_channels[i];
@@ -2647,7 +2675,7 @@ int ipa3_mhi_suspend(bool force)
return res;
}
force_clear = true;
- IPA_MHI_DBG("force clear datapath enabled\n");
+ IPA_MHI_DBG_LOW("force clear datapath enabled\n");
empty = ipa3_mhi_wait_for_ul_empty_timeout(
IPA_MHI_CH_EMPTY_TIMEOUT_MSEC);
@@ -2676,7 +2704,7 @@ int ipa3_mhi_suspend(bool force)
BUG();
return res;
}
- IPA_MHI_DBG("force clear datapath disabled\n");
+ IPA_MHI_DBG_LOW("force clear datapath disabled\n");
ipa3_mhi_ctx->qmi_req_id++;
}
@@ -2701,14 +2729,14 @@ int ipa3_mhi_suspend(bool force)
*/
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- IPA_MHI_DBG("release prod\n");
+ IPA_MHI_DBG_LOW("release prod\n");
res = ipa3_mhi_release_prod();
if (res) {
IPA_MHI_ERR("ipa3_mhi_release_prod failed %d\n", res);
goto fail_release_prod;
}
- IPA_MHI_DBG("wait for cons release\n");
+ IPA_MHI_DBG_LOW("wait for cons release\n");
res = ipa3_mhi_wait_for_cons_release();
if (res) {
IPA_MHI_ERR("ipa3_mhi_wait_for_cons_release failed %d\n", res);
@@ -2772,7 +2800,7 @@ fail_suspend_ul_channel:
IPA_MHI_ERR("failed to disable force clear\n");
BUG();
}
- IPA_MHI_DBG("force clear datapath disabled\n");
+ IPA_MHI_DBG_LOW("force clear datapath disabled\n");
ipa3_mhi_ctx->qmi_req_id++;
}
return res;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
index 4cd655aa8124..6444dcf3cfdc 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
@@ -356,7 +356,7 @@ static void ipa3_a5_svc_recv_msg(struct work_struct *work)
int rc;
do {
- IPAWANDBG("Notified about a Receive Event");
+ IPAWANDBG_LOW("Notified about a Receive Event");
rc = qmi_recv_msg(ipa3_svc_handle);
} while (rc == 0);
if (rc != -ENOMSG)
@@ -430,7 +430,7 @@ static int ipa3_check_qmi_response(int rc,
req_id, result, error);
return result;
}
- IPAWANDBG("Received %s successfully\n", resp_type);
+ IPAWANDBG_LOW("Received %s successfully\n", resp_type);
return 0;
}
@@ -762,7 +762,7 @@ static void ipa3_q6_clnt_recv_msg(struct work_struct *work)
int rc;
do {
- IPAWANDBG("Notified about a Receive Event");
+ IPAWANDBG_LOW("Notified about a Receive Event");
rc = qmi_recv_msg(ipa_q6_clnt);
} while (rc == 0);
if (rc != -ENOMSG)
@@ -774,7 +774,7 @@ static void ipa3_q6_clnt_notify(struct qmi_handle *handle,
{
switch (event) {
case QMI_RECV_MSG:
- IPAWANDBG("client qmi recv message called");
+ IPAWANDBG_LOW("client qmi recv message called");
if (!workqueues_stopped)
queue_delayed_work(ipa_clnt_resp_workqueue,
&ipa3_work_recv_msg_client, 0);
@@ -1154,7 +1154,7 @@ int ipa3_qmi_get_data_stats(struct ipa_get_data_stats_req_msg_v01 *req,
resp_desc.msg_id = QMI_IPA_GET_DATA_STATS_RESP_V01;
resp_desc.ei_array = ipa3_get_data_stats_resp_msg_data_v01_ei;
- IPAWANDBG("Sending QMI_IPA_GET_DATA_STATS_REQ_V01\n");
+ IPAWANDBG_LOW("Sending QMI_IPA_GET_DATA_STATS_REQ_V01\n");
rc = qmi_send_req_wait(ipa_q6_clnt, &req_desc, req,
sizeof(struct ipa_get_data_stats_req_msg_v01),
@@ -1162,7 +1162,7 @@ int ipa3_qmi_get_data_stats(struct ipa_get_data_stats_req_msg_v01 *req,
sizeof(struct ipa_get_data_stats_resp_msg_v01),
QMI_SEND_STATS_REQ_TIMEOUT_MS);
- IPAWANDBG("QMI_IPA_GET_DATA_STATS_RESP_V01 received\n");
+ IPAWANDBG_LOW("QMI_IPA_GET_DATA_STATS_RESP_V01 received\n");
return ipa3_check_qmi_response(rc,
QMI_IPA_GET_DATA_STATS_REQ_V01, resp->resp.result,
@@ -1183,7 +1183,7 @@ int ipa3_qmi_get_network_stats(struct ipa_get_apn_data_stats_req_msg_v01 *req,
resp_desc.msg_id = QMI_IPA_GET_APN_DATA_STATS_RESP_V01;
resp_desc.ei_array = ipa3_get_apn_data_stats_resp_msg_data_v01_ei;
- IPAWANDBG("Sending QMI_IPA_GET_APN_DATA_STATS_REQ_V01\n");
+ IPAWANDBG_LOW("Sending QMI_IPA_GET_APN_DATA_STATS_REQ_V01\n");
rc = qmi_send_req_wait(ipa_q6_clnt, &req_desc, req,
sizeof(struct ipa_get_apn_data_stats_req_msg_v01),
@@ -1191,7 +1191,7 @@ int ipa3_qmi_get_network_stats(struct ipa_get_apn_data_stats_req_msg_v01 *req,
sizeof(struct ipa_get_apn_data_stats_resp_msg_v01),
QMI_SEND_STATS_REQ_TIMEOUT_MS);
- IPAWANDBG("QMI_IPA_GET_APN_DATA_STATS_RESP_V01 received\n");
+ IPAWANDBG_LOW("QMI_IPA_GET_APN_DATA_STATS_RESP_V01 received\n");
return ipa3_check_qmi_response(rc,
QMI_IPA_GET_APN_DATA_STATS_REQ_V01, resp->resp.result,
@@ -1215,14 +1215,14 @@ int ipa3_qmi_set_data_quota(struct ipa_set_data_usage_quota_req_msg_v01 *req)
resp_desc.msg_id = QMI_IPA_SET_DATA_USAGE_QUOTA_RESP_V01;
resp_desc.ei_array = ipa3_set_data_usage_quota_resp_msg_data_v01_ei;
- IPAWANDBG("Sending QMI_IPA_SET_DATA_USAGE_QUOTA_REQ_V01\n");
+ IPAWANDBG_LOW("Sending QMI_IPA_SET_DATA_USAGE_QUOTA_REQ_V01\n");
rc = qmi_send_req_wait(ipa_q6_clnt, &req_desc, req,
sizeof(struct ipa_set_data_usage_quota_req_msg_v01),
&resp_desc, &resp, sizeof(resp),
QMI_SEND_STATS_REQ_TIMEOUT_MS);
- IPAWANDBG("QMI_IPA_SET_DATA_USAGE_QUOTA_RESP_V01 received\n");
+ IPAWANDBG_LOW("QMI_IPA_SET_DATA_USAGE_QUOTA_RESP_V01 received\n");
return ipa3_check_qmi_response(rc,
QMI_IPA_SET_DATA_USAGE_QUOTA_REQ_V01, resp.resp.result,
@@ -1249,13 +1249,13 @@ int ipa3_qmi_stop_data_qouta(void)
resp_desc.msg_id = QMI_IPA_STOP_DATA_USAGE_QUOTA_RESP_V01;
resp_desc.ei_array = ipa3_stop_data_usage_quota_resp_msg_data_v01_ei;
- IPAWANDBG("Sending QMI_IPA_STOP_DATA_USAGE_QUOTA_REQ_V01\n");
+ IPAWANDBG_LOW("Sending QMI_IPA_STOP_DATA_USAGE_QUOTA_REQ_V01\n");
rc = qmi_send_req_wait(ipa_q6_clnt, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp),
QMI_SEND_STATS_REQ_TIMEOUT_MS);
- IPAWANDBG("QMI_IPA_STOP_DATA_USAGE_QUOTA_RESP_V01 received\n");
+ IPAWANDBG_LOW("QMI_IPA_STOP_DATA_USAGE_QUOTA_RESP_V01 received\n");
return ipa3_check_qmi_response(rc,
QMI_IPA_STOP_DATA_USAGE_QUOTA_REQ_V01, resp.resp.result,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
index 5f6722d3fbac..0f641204cc77 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
@@ -31,11 +31,39 @@
#define SUBSYS_MODEM "modem"
#define IPAWANDBG(fmt, args...) \
- pr_debug(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+ do { \
+ pr_debug(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ DEV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ DEV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+
+#define IPAWANDBG_LOW(fmt, args...) \
+ do { \
+ pr_debug(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ DEV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
#define IPAWANERR(fmt, args...) \
- pr_err(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+ do { \
+ pr_err(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ DEV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ DEV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
#define IPAWANINFO(fmt, args...) \
- pr_info(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+ do { \
+ pr_info(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ DEV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ DEV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
extern struct ipa3_qmi_context *ipa3_qmi_ctx;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index 9f98d3ffef30..d0b1b525d95a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -1018,6 +1018,229 @@ static void ipahal_debugfs_init(void) {}
static void ipahal_debugfs_remove(void) {}
#endif /* CONFIG_DEBUG_FS */
+/*
+ * ipahal_cp_hdr_to_hw_buff_v3() - copy header to hardware buffer according to
+ * base address and offset given.
+ * @base: dma base address
+ * @offset: offset from base address where the data will be copied
+ * @hdr: the header to be copied
+ * @hdr_len: the length of the header
+ */
+static void ipahal_cp_hdr_to_hw_buff_v3(void *const base, u32 offset,
+ u8 *const hdr, u32 hdr_len)
+{
+ memcpy(base + offset, hdr, hdr_len);
+}
+
+/*
+ * ipahal_cp_proc_ctx_to_hw_buff_v3() - copy processing context to
+ * base address and offset given.
+ * @type: header processing context type (no processing context,
+ * IPA_HDR_PROC_ETHII_TO_ETHII etc.)
+ * @base: dma base address
+ * @offset: offset from base address where the data will be copied
+ * @hdr_len: the length of the header
+ * @is_hdr_proc_ctx: header is located in phys_base (true) or hdr_base_addr
+ * @phys_base: memory location in DDR
+ * @hdr_base_addr: base address in table
+ * @hdr_offset_entry: offset from hdr_base_addr in table
+ */
+static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type,
+ void *const base, u32 offset,
+ u32 hdr_len, bool is_hdr_proc_ctx,
+ dma_addr_t phys_base, u32 hdr_base_addr,
+ u32 hdr_offset_entry){
+ if (type == IPA_HDR_PROC_NONE) {
+ struct ipa_hw_hdr_proc_ctx_add_hdr_seq *ctx;
+
+ ctx = (struct ipa_hw_hdr_proc_ctx_add_hdr_seq *)
+ (base + offset);
+ ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
+ ctx->hdr_add.tlv.length = 1;
+ ctx->hdr_add.tlv.value = hdr_len;
+ ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
+ hdr_base_addr + hdr_offset_entry;
+ IPAHAL_DBG("header address 0x%x\n",
+ ctx->hdr_add.hdr_addr);
+ ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
+ ctx->end.length = 0;
+ ctx->end.value = 0;
+ } else {
+ struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq *ctx;
+
+ ctx = (struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq *)
+ (base + offset);
+ ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
+ ctx->hdr_add.tlv.length = 1;
+ ctx->hdr_add.tlv.value = hdr_len;
+ ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
+ hdr_base_addr + hdr_offset_entry;
+ IPAHAL_DBG("header address 0x%x\n",
+ ctx->hdr_add.hdr_addr);
+ ctx->cmd.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD;
+ ctx->cmd.length = 0;
+ switch (type) {
+ case IPA_HDR_PROC_ETHII_TO_ETHII:
+ ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_ETHII;
+ break;
+ case IPA_HDR_PROC_ETHII_TO_802_3:
+ ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_802_3;
+ break;
+ case IPA_HDR_PROC_802_3_TO_ETHII:
+ ctx->cmd.value = IPA_HDR_UCP_802_3_TO_ETHII;
+ break;
+ case IPA_HDR_PROC_802_3_TO_802_3:
+ ctx->cmd.value = IPA_HDR_UCP_802_3_TO_802_3;
+ break;
+ default:
+ IPAHAL_ERR("unknown ipa_hdr_proc_type %d", type);
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ IPAHAL_DBG("command id %d\n", ctx->cmd.value);
+ ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
+ ctx->end.length = 0;
+ ctx->end.value = 0;
+ }
+
+ return 0;
+}
+
+/*
+ * ipahal_get_proc_ctx_needed_len_v3() - calculates the needed length for
+ * addition of header processing context according to the type of processing
+ * context.
+ * @type: header processing context type (no processing context,
+ * IPA_HDR_PROC_ETHII_TO_ETHII etc.)
+ */
+static int ipahal_get_proc_ctx_needed_len_v3(enum ipa_hdr_proc_type type)
+{
+ return (type == IPA_HDR_PROC_NONE) ?
+ sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_seq) :
+ sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq);
+}
+
+/*
+ * struct ipahal_hdr_funcs - headers handling functions for specific IPA
+ * version
+ * @ipahal_cp_hdr_to_hw_buff - copy function for regular headers
+ */
+struct ipahal_hdr_funcs {
+ void (*ipahal_cp_hdr_to_hw_buff)(void *const base, u32 offset,
+ u8 *const hdr, u32 hdr_len);
+
+ int (*ipahal_cp_proc_ctx_to_hw_buff)(enum ipa_hdr_proc_type type,
+ void *const base, u32 offset, u32 hdr_len,
+ bool is_hdr_proc_ctx, dma_addr_t phys_base,
+ u32 hdr_base_addr, u32 hdr_offset_entry);
+
+ int (*ipahal_get_proc_ctx_needed_len)(enum ipa_hdr_proc_type type);
+};
+
+static struct ipahal_hdr_funcs hdr_funcs;
+
+static void ipahal_hdr_init(enum ipa_hw_type ipa_hw_type)
+{
+
+ IPAHAL_DBG("Entry - HW_TYPE=%d\n", ipa_hw_type);
+
+ /*
+ * once there are changes in HW and need to use different case, insert
+ * new case for the new h/w. put the default always for the latest HW
+ * and make sure all previous supported versions have their cases.
+ */
+ switch (ipa_hw_type) {
+ case IPA_HW_v3_0:
+ default:
+ hdr_funcs.ipahal_cp_hdr_to_hw_buff =
+ ipahal_cp_hdr_to_hw_buff_v3;
+ hdr_funcs.ipahal_cp_proc_ctx_to_hw_buff =
+ ipahal_cp_proc_ctx_to_hw_buff_v3;
+ hdr_funcs.ipahal_get_proc_ctx_needed_len =
+ ipahal_get_proc_ctx_needed_len_v3;
+ }
+ IPAHAL_DBG("Exit\n");
+}
+
+/*
+ * ipahal_cp_hdr_to_hw_buff() - copy header to hardware buffer according to
+ * base address and offset given.
+ * @base: dma base address
+ * @offset: offset from base address where the data will be copied
+ * @hdr: the header to be copied
+ * @hdr_len: the length of the header
+ */
+void ipahal_cp_hdr_to_hw_buff(void *base, u32 offset, u8 *const hdr,
+ u32 hdr_len)
+{
+ IPAHAL_DBG_LOW("Entry\n");
+ IPAHAL_DBG("base %p, offset %d, hdr %p, hdr_len %d\n", base,
+ offset, hdr, hdr_len);
+ if (!base || !hdr_len || !hdr) {
+ IPAHAL_ERR("failed on validating params");
+ return;
+ }
+
+ hdr_funcs.ipahal_cp_hdr_to_hw_buff(base, offset, hdr, hdr_len);
+
+ IPAHAL_DBG_LOW("Exit\n");
+}
+
+/*
+ * ipahal_cp_proc_ctx_to_hw_buff() - copy processing context to
+ * base address and offset given.
+ * @type: type of header processing context
+ * @base: dma base address
+ * @offset: offset from base address where the data will be copied
+ * @hdr_len: the length of the header
+ * @is_hdr_proc_ctx: header is located in phys_base (true) or hdr_base_addr
+ * @phys_base: memory location in DDR
+ * @hdr_base_addr: base address in table
+ * @hdr_offset_entry: offset from hdr_base_addr in table
+ */
+int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
+ void *const base, u32 offset, u32 hdr_len,
+ bool is_hdr_proc_ctx, dma_addr_t phys_base,
+ u32 hdr_base_addr, u32 hdr_offset_entry)
+{
+ IPAHAL_DBG(
+ "type %d, base %p, offset %d, hdr_len %d, is_hdr_proc_ctx %d, hdr_base_addr %d, hdr_offset_entry %d\n"
+ , type, base, offset, hdr_len, is_hdr_proc_ctx,
+ hdr_base_addr, hdr_offset_entry);
+
+ if (!base ||
+ !hdr_len ||
+ (!phys_base && !hdr_base_addr) ||
+ !hdr_base_addr) {
+ IPAHAL_ERR("failed on validating params");
+ return -EINVAL;
+ }
+
+ return hdr_funcs.ipahal_cp_proc_ctx_to_hw_buff(type, base, offset,
+ hdr_len, is_hdr_proc_ctx, phys_base,
+ hdr_base_addr, hdr_offset_entry);
+}
+
+/*
+ * ipahal_get_proc_ctx_needed_len() - calculates the needed length for
+ * addition of header processing context according to the type of processing
+ * context
+ * @type: header processing context type (no processing context,
+ * IPA_HDR_PROC_ETHII_TO_ETHII etc.)
+ */
+int ipahal_get_proc_ctx_needed_len(enum ipa_hdr_proc_type type)
+{
+ int res;
+
+ IPAHAL_DBG("entry\n");
+
+ res = hdr_funcs.ipahal_get_proc_ctx_needed_len(type);
+
+ IPAHAL_DBG("Exit\n");
+
+ return res;
+}
+
int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base)
{
int result;
@@ -1065,6 +1288,8 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base)
goto bail_free_ctx;
}
+ ipahal_hdr_init(ipa_hw_type);
+
ipahal_debugfs_init();
return 0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
index 8591ff046624..13812585ff6f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
@@ -597,6 +597,41 @@ void ipahal_pkt_status_parse(const void *unparsed_status,
const char *ipahal_pkt_status_exception_str(
enum ipahal_pkt_status_exception exception);
+/*
+ * ipahal_cp_hdr_to_hw_buff() - copy header to hardware buffer according to
+ * base address and offset given.
+ * @base: dma base address
+ * @offset: offset from base address where the data will be copied
+ * @hdr: the header to be copied
+ * @hdr_len: the length of the header
+ */
+void ipahal_cp_hdr_to_hw_buff(void *base, u32 offset, u8 *hdr, u32 hdr_len);
+
+/*
+ * ipahal_cp_proc_ctx_to_hw_buff() - copy processing context to
+ * base address and offset given.
+ * @type: type of header processing context
+ * @base: dma base address
+ * @offset: offset from base address where the data will be copied
+ * @hdr_len: the length of the header
+ * @is_hdr_proc_ctx: header is located in phys_base (true) or hdr_base_addr
+ * @phys_base: memory location in DDR
+ * @hdr_base_addr: base address in table
+ * @hdr_offset_entry: offset from hdr_base_addr in table
+ */
+int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
+ void *base, u32 offset, u32 hdr_len,
+ bool is_hdr_proc_ctx, dma_addr_t phys_base,
+ u32 hdr_base_addr, u32 hdr_offset_entry);
+
+/*
+ * ipahal_get_proc_ctx_needed_len() - calculates the needed length for addition
+ * of header processing context according to the type of processing context
+ * @type: header processing context type (no processing context,
+ * IPA_HDR_PROC_ETHII_TO_ETHII etc.)
+ */
+int ipahal_get_proc_ctx_needed_len(enum ipa_hdr_proc_type type);
+
int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base);
void ipahal_destroy(void);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
index 9b348d6f969e..6a22240e951b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
@@ -471,4 +471,75 @@ struct ipa_pkt_status_hw {
/* Size of H/W Packet Status */
#define IPA3_0_PKT_STATUS_SIZE 32
+/* Headers and processing context H/W structures and definitions */
+
+/* uCP command numbers */
+#define IPA_HDR_UCP_802_3_TO_802_3 6
+#define IPA_HDR_UCP_802_3_TO_ETHII 7
+#define IPA_HDR_UCP_ETHII_TO_802_3 8
+#define IPA_HDR_UCP_ETHII_TO_ETHII 9
+
+/* Processing context TLV type */
+#define IPA_PROC_CTX_TLV_TYPE_END 0
+#define IPA_PROC_CTX_TLV_TYPE_HDR_ADD 1
+#define IPA_PROC_CTX_TLV_TYPE_PROC_CMD 3
+
+/**
+ * struct ipa_hw_hdr_proc_ctx_tlv -
+ * HW structure of IPA processing context header - TLV part
+ * @type: 0 - end type
+ * 1 - header addition type
+ * 3 - processing command type
+ * @length: number of bytes after tlv
+ * for type:
+ * 0 - needs to be 0
+ * 1 - header addition length
+ * 3 - number of 32B including type and length.
+ * @value: specific value for type
+ * for type:
+ * 0 - needs to be 0
+ * 1 - header length
+ * 3 - command ID (see IPA_HDR_UCP_* definitions)
+ */
+struct ipa_hw_hdr_proc_ctx_tlv {
+ u32 type:8;
+ u32 length:8;
+ u32 value:16;
+};
+
+/**
+ * struct ipa_hw_hdr_proc_ctx_hdr_add -
+ * HW structure of IPA processing context - add header tlv
+ * @tlv: IPA processing context TLV
+ * @hdr_addr: processing context header address
+ */
+struct ipa_hw_hdr_proc_ctx_hdr_add {
+ struct ipa_hw_hdr_proc_ctx_tlv tlv;
+ u32 hdr_addr;
+};
+
+/**
+ * struct ipa_hw_hdr_proc_ctx_add_hdr_seq -
+ * IPA processing context header - add header sequence
+ * @hdr_add: add header command
+ * @end: tlv end command (cmd.type must be 0)
+ */
+struct ipa_hw_hdr_proc_ctx_add_hdr_seq {
+ struct ipa_hw_hdr_proc_ctx_hdr_add hdr_add;
+ struct ipa_hw_hdr_proc_ctx_tlv end;
+};
+
+/**
+ * struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq -
+ * IPA processing context header - process command sequence
+ * @hdr_add: add header command
+ * @cmd: tlv processing command (cmd.type must be 3)
+ * @end: tlv end command (cmd.type must be 0)
+ */
+struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq {
+ struct ipa_hw_hdr_proc_ctx_hdr_add hdr_add;
+ struct ipa_hw_hdr_proc_ctx_tlv cmd;
+ struct ipa_hw_hdr_proc_ctx_tlv end;
+};
+
#endif /* _IPAHAL_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index 8a34f006d3ee..928856f7f38b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -1051,7 +1051,7 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev)
struct ipa_tx_meta meta;
if (skb->protocol != htons(ETH_P_MAP)) {
- IPAWANDBG
+ IPAWANDBG_LOW
("SW filtering out none QMAP packet received from %s",
current->comm);
return NETDEV_TX_OK;
@@ -1074,11 +1074,11 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev)
if (atomic_read(&wwan_ptr->outstanding_pkts) >=
wwan_ptr->outstanding_high) {
if (!qmap_check) {
- IPAWANDBG("pending(%d)/(%d)- stop(%d), qmap_chk(%d)\n",
+ IPAWANDBG_LOW("pending(%d)/(%d)- stop(%d)\n",
atomic_read(&wwan_ptr->outstanding_pkts),
wwan_ptr->outstanding_high,
- netif_queue_stopped(dev),
- qmap_check);
+ netif_queue_stopped(dev));
+ IPAWANDBG_LOW("qmap_chk(%d)\n", qmap_check);
netif_stop_queue(dev);
return NETDEV_TX_BUSY;
}
@@ -1165,7 +1165,7 @@ static void apps_ipa_tx_complete_notify(void *priv,
netif_queue_stopped(wwan_ptr->net) &&
atomic_read(&wwan_ptr->outstanding_pkts) <
(wwan_ptr->outstanding_low)) {
- IPAWANDBG("Outstanding low (%d) - waking up queue\n",
+ IPAWANDBG_LOW("Outstanding low (%d) - waking up queue\n",
wwan_ptr->outstanding_low);
netif_wake_queue(wwan_ptr->net);
}
@@ -1193,7 +1193,7 @@ static void apps_ipa_packet_receive_notify(void *priv,
int result;
unsigned int packet_len = skb->len;
- IPAWANDBG("Rx packet was received");
+ IPAWANDBG_LOW("Rx packet was received");
if (evt != IPA_RECEIVE) {
IPAWANERR("A none IPA_RECEIVE event in wan_ipa_receive\n");
return;
@@ -1733,10 +1733,10 @@ static void ipa3_q6_rm_notify_cb(void *user_data,
{
switch (event) {
case IPA_RM_RESOURCE_GRANTED:
- IPAWANDBG("%s: Q6_PROD GRANTED CB\n", __func__);
+ IPAWANDBG_LOW("%s: Q6_PROD GRANTED CB\n", __func__);
break;
case IPA_RM_RESOURCE_RELEASED:
- IPAWANDBG("%s: Q6_PROD RELEASED CB\n", __func__);
+ IPAWANDBG_LOW("%s: Q6_PROD RELEASED CB\n", __func__);
break;
default:
return;
@@ -1843,7 +1843,7 @@ static void ipa3_wake_tx_queue(struct work_struct *work)
*/
static void ipa3_rm_resource_granted(void *dev)
{
- IPAWANDBG("Resource Granted - starting queue\n");
+ IPAWANDBG_LOW("Resource Granted - starting queue\n");
schedule_work(&ipa3_tx_wakequeue_work);
}
@@ -2209,7 +2209,7 @@ static int rmnet_ipa_ap_suspend(struct device *dev)
struct net_device *netdev = IPA_NETDEV();
struct ipa3_wwan_private *wwan_ptr;
- IPAWANDBG("Enter...\n");
+ IPAWANDBG_LOW("Enter...\n");
if (netdev == NULL) {
IPAWANERR("netdev is NULL.\n");
return 0;
@@ -2231,7 +2231,7 @@ static int rmnet_ipa_ap_suspend(struct device *dev)
netif_tx_lock_bh(netdev);
ipa_rm_release_resource(IPA_RM_RESOURCE_WWAN_0_PROD);
netif_tx_unlock_bh(netdev);
- IPAWANDBG("Exit\n");
+ IPAWANDBG_LOW("Exit\n");
return 0;
}
@@ -2250,10 +2250,10 @@ static int rmnet_ipa_ap_resume(struct device *dev)
{
struct net_device *netdev = IPA_NETDEV();
- IPAWANDBG("Enter...\n");
+ IPAWANDBG_LOW("Enter...\n");
if (netdev)
netif_wake_queue(netdev);
- IPAWANDBG("Exit\n");
+ IPAWANDBG_LOW("Exit\n");
return 0;
}
@@ -2337,7 +2337,7 @@ static int ipa3_ssr_notifier_cb(struct notifier_block *this,
break;
}
- IPAWANDBG("Exit\n");
+ IPAWANDBG_LOW("Exit\n");
return NOTIFY_DONE;
}
@@ -2614,7 +2614,7 @@ int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data,
IPAWANERR("reset the pipe stats\n");
} else {
/* print tethered-client enum */
- IPAWANDBG("Tethered-client enum(%d)\n", data->ipa_client);
+ IPAWANDBG_LOW("Tethered-client enum(%d)\n", data->ipa_client);
}
rc = ipa3_qmi_get_data_stats(req, resp);
@@ -2632,16 +2632,17 @@ int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data,
if (resp->dl_dst_pipe_stats_list_valid) {
for (pipe_len = 0; pipe_len < resp->dl_dst_pipe_stats_list_len;
pipe_len++) {
- IPAWANDBG("Check entry(%d) dl_dst_pipe(%d)\n",
+ IPAWANDBG_LOW("Check entry(%d) dl_dst_pipe(%d)\n",
pipe_len, resp->dl_dst_pipe_stats_list
[pipe_len].pipe_index);
- IPAWANDBG("dl_p_v4(%lu)v6(%lu) dl_b_v4(%lu)v6(%lu)\n",
+ IPAWANDBG_LOW("dl_p_v4(%lu)v6(%lu)\n",
(unsigned long int) resp->
dl_dst_pipe_stats_list[pipe_len].
num_ipv4_packets,
(unsigned long int) resp->
dl_dst_pipe_stats_list[pipe_len].
- num_ipv6_packets,
+ num_ipv6_packets);
+ IPAWANDBG_LOW("dl_b_v4(%lu)v6(%lu)\n",
(unsigned long int) resp->
dl_dst_pipe_stats_list[pipe_len].
num_ipv4_bytes,
@@ -2671,7 +2672,7 @@ int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data,
}
}
}
- IPAWANDBG("v4_rx_p(%lu) v6_rx_p(%lu) v4_rx_b(%lu) v6_rx_b(%lu)\n",
+ IPAWANDBG_LOW("v4_rx_p(%lu) v6_rx_p(%lu) v4_rx_b(%lu) v6_rx_b(%lu)\n",
(unsigned long int) data->ipv4_rx_packets,
(unsigned long int) data->ipv6_rx_packets,
(unsigned long int) data->ipv4_rx_bytes,
@@ -2680,17 +2681,18 @@ int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data,
if (resp->ul_src_pipe_stats_list_valid) {
for (pipe_len = 0; pipe_len < resp->ul_src_pipe_stats_list_len;
pipe_len++) {
- IPAWANDBG("Check entry(%d) ul_dst_pipe(%d)\n",
+ IPAWANDBG_LOW("Check entry(%d) ul_dst_pipe(%d)\n",
pipe_len,
resp->ul_src_pipe_stats_list[pipe_len].
pipe_index);
- IPAWANDBG("ul_p_v4(%lu)v6(%lu)ul_b_v4(%lu)v6(%lu)\n",
+ IPAWANDBG_LOW("ul_p_v4(%lu)v6(%lu)\n",
(unsigned long int) resp->
ul_src_pipe_stats_list[pipe_len].
num_ipv4_packets,
(unsigned long int) resp->
ul_src_pipe_stats_list[pipe_len].
- num_ipv6_packets,
+ num_ipv6_packets);
+ IPAWANDBG_LOW("ul_b_v4(%lu)v6(%lu)\n",
(unsigned long int) resp->
ul_src_pipe_stats_list[pipe_len].
num_ipv4_bytes,
@@ -2720,7 +2722,7 @@ int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data,
}
}
}
- IPAWANDBG("tx_p_v4(%lu)v6(%lu)tx_b_v4(%lu) v6(%lu)\n",
+ IPAWANDBG_LOW("tx_p_v4(%lu)v6(%lu)tx_b_v4(%lu) v6(%lu)\n",
(unsigned long int) data->ipv4_tx_packets,
(unsigned long int) data->ipv6_tx_packets,
(unsigned long int) data->ipv4_tx_bytes,
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c
index 608e6f23435e..80b07ab79163 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -147,8 +147,7 @@ static long ipa3_wan_ioctl(struct file *filp,
break;
case WAN_IOC_POLL_TETHERING_STATS:
- IPAWANDBG("device %s got WAN_IOCTL_POLL_TETHERING_STATS :>>>\n",
- DRIVER_NAME);
+ IPAWANDBG_LOW("got WAN_IOCTL_POLL_TETHERING_STATS :>>>\n");
pyld_sz = sizeof(struct wan_ioctl_poll_tethering_stats);
param = kzalloc(pyld_sz, GFP_KERNEL);
if (!param) {
@@ -172,8 +171,7 @@ static long ipa3_wan_ioctl(struct file *filp,
break;
case WAN_IOC_SET_DATA_QUOTA:
- IPAWANDBG("device %s got WAN_IOCTL_SET_DATA_QUOTA :>>>\n",
- DRIVER_NAME);
+ IPAWANDBG_LOW("got WAN_IOCTL_SET_DATA_QUOTA :>>>\n");
pyld_sz = sizeof(struct wan_ioctl_set_data_quota);
param = kzalloc(pyld_sz, GFP_KERNEL);
if (!param) {
@@ -197,8 +195,7 @@ static long ipa3_wan_ioctl(struct file *filp,
break;
case WAN_IOC_SET_TETHER_CLIENT_PIPE:
- IPAWANDBG("device %s got WAN_IOC_SET_TETHER_CLIENT_PIPE :>>>\n",
- DRIVER_NAME);
+ IPAWANDBG_LOW("got WAN_IOC_SET_TETHER_CLIENT_PIPE :>>>\n");
pyld_sz = sizeof(struct wan_ioctl_set_tether_client_pipe);
param = kzalloc(pyld_sz, GFP_KERNEL);
if (!param) {
@@ -218,8 +215,7 @@ static long ipa3_wan_ioctl(struct file *filp,
break;
case WAN_IOC_QUERY_TETHER_STATS:
- IPAWANDBG("device %s got WAN_IOC_QUERY_TETHER_STATS :>>>\n",
- DRIVER_NAME);
+ IPAWANDBG_LOW("got WAN_IOC_QUERY_TETHER_STATS :>>>\n");
pyld_sz = sizeof(struct wan_ioctl_query_tether_stats);
param = kzalloc(pyld_sz, GFP_KERNEL);
if (!param) {
@@ -245,7 +241,7 @@ static long ipa3_wan_ioctl(struct file *filp,
break;
case WAN_IOC_RESET_TETHER_STATS:
- IPAWANDBG("device %s got WAN_IOC_RESET_TETHER_STATS :>>>\n",
+ IPAWANDBG_LOW("device %s got WAN_IOC_RESET_TETHER_STATS :>>>\n",
DRIVER_NAME);
pyld_sz = sizeof(struct wan_ioctl_reset_tether_stats);
param = kzalloc(pyld_sz, GFP_KERNEL);
diff --git a/drivers/platform/msm/msm_11ad/msm_11ad.c b/drivers/platform/msm/msm_11ad/msm_11ad.c
index a8adc2401dbf..6d826590cabc 100644
--- a/drivers/platform/msm/msm_11ad/msm_11ad.c
+++ b/drivers/platform/msm/msm_11ad/msm_11ad.c
@@ -1102,17 +1102,15 @@ static int ops_notify(void *handle, enum wil_platform_event evt)
break;
case WIL_PLATFORM_EVT_PRE_RESET:
/*
- * Enable rf_clk3 clock before resetting the device to ensure
- * stable ref clock during the device reset
+ * TODO: Enable rf_clk3 clock before resetting the device to
+ * ensure stable ref clock during the device reset
*/
- rc = msm_11ad_enable_clk(ctx, &ctx->rf_clk3);
break;
case WIL_PLATFORM_EVT_FW_RDY:
/*
- * Disable rf_clk3 clock after the device is up to allow
+ * TODO: Disable rf_clk3 clock after the device is up to allow
* the device to control it via its GPIO for power saving
*/
- msm_11ad_disable_clk(ctx, &ctx->rf_clk3);
break;
default:
pr_debug("%s: Unhandled event %d\n", __func__, evt);
diff --git a/drivers/regulator/cpr3-mmss-regulator.c b/drivers/regulator/cpr3-mmss-regulator.c
index d32db884989e..c80b6b703e26 100644
--- a/drivers/regulator/cpr3-mmss-regulator.c
+++ b/drivers/regulator/cpr3-mmss-regulator.c
@@ -191,6 +191,14 @@ static const int msm8996pro_mmss_fuse_ref_volt[MSM8996_MMSS_FUSE_CORNERS] = {
};
static const int msmcobalt_mmss_fuse_ref_volt[MSM8996_MMSS_FUSE_CORNERS] = {
+ 528000,
+ 656000,
+ 812000,
+ 932000,
+};
+
+static const int
+msmcobalt_rev0_mmss_fuse_ref_volt[MSM8996_MMSS_FUSE_CORNERS] = {
632000,
768000,
896000,
@@ -694,7 +702,10 @@ static int cpr3_msm8996_mmss_calculate_open_loop_voltages(
goto done;
}
- if (vreg->thread->ctrl->soc_revision == MSMCOBALT_SOC_ID)
+ if (vreg->thread->ctrl->soc_revision == MSMCOBALT_SOC_ID
+ && fuse->cpr_fusing_rev == 0)
+ ref_volt = msmcobalt_rev0_mmss_fuse_ref_volt;
+ else if (vreg->thread->ctrl->soc_revision == MSMCOBALT_SOC_ID)
ref_volt = msmcobalt_mmss_fuse_ref_volt;
else if (vreg->thread->ctrl->soc_revision == MSM8996PRO_SOC_ID)
ref_volt = msm8996pro_mmss_fuse_ref_volt;
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 5cd1a519693f..3fa75cc19a4f 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -668,4 +668,35 @@ config MSM_SERVICE_NOTIFIER
like audio, the identifier for which is provided by the service
locator.
+config MSM_RPM_RBCPR_STATS_V2_LOG
+ tristate "MSM Resource Power Manager RPBCPR Stat Driver"
+ depends on DEBUG_FS
+ help
+ This option enables v2 of the rpmrbcpr_stats driver which reads RPM
+ memory for statistics pertaining to RPM's RBCPR(Rapid Bridge Core
+ Power Reduction) driver. The drivers outputs the message via a
+ debugfs node.
+
+config MSM_RPM_LOG
+ tristate "MSM Resource Power Manager Log Driver"
+ depends on DEBUG_FS
+ depends on MSM_RPM_SMD
+ default n
+ help
+ This option enables a driver which can read from a circular buffer
+ of messages produced by the RPM. These messages provide diagnostic
+ information about RPM operation. The driver outputs the messages
+ via a debugfs node.
+
+config MSM_RPM_STATS_LOG
+ tristate "MSM Resource Power Manager Stat Driver"
+ depends on DEBUG_FS
+ depends on MSM_RPM_SMD
+ default n
+ help
+ This option enables a driver which reads RPM messages from a shared
+ memory location. These messages provide statistical information about
+ the low power modes that RPM enters. The drivers outputs the message
+ via a debugfs node.
+
source "drivers/soc/qcom/memshare/Kconfig"
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 2433e81a831b..2cb810465002 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -85,3 +85,6 @@ obj-$(CONFIG_MSM_KERNEL_PROTECT) += kernel_protect.o
obj-$(CONFIG_MSM_RTB) += msm_rtb-hotplug.o
obj-$(CONFIG_QCOM_REMOTEQDSS) += remoteqdss.o
obj-$(CONFIG_MSM_SERVICE_LOCATOR) += service-locator.o
+obj-$(CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG) += rpm_rbcpr_stats_v2.o
+obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o rpm_master_stat.o
+obj-$(CONFIG_MSM_RPM_LOG) += rpm_log.o
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 887e49e3beb6..a64fdac00ff4 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -9,6 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#include <asm/dma-iommu.h>
+#include <linux/clk.h>
+#include <linux/iommu.h>
#include <linux/export.h>
#include <linux/err.h>
#include <linux/of.h>
@@ -45,6 +48,7 @@ struct icnss_qmi_event {
#define WLFW_SERVICE_INS_ID_V01 0
#define ICNSS_WLFW_QMI_CONNECTED BIT(0)
#define ICNSS_FW_READY BIT(1)
+#define SMMU_CLOCK_NAME "smmu_aggre2_noc_clk"
#define ICNSS_IS_WLFW_QMI_CONNECTED(_state) \
((_state) & ICNSS_WLFW_QMI_CONNECTED)
@@ -84,6 +88,10 @@ static struct {
void __iomem *mem_base_va;
phys_addr_t mpm_config_pa;
void __iomem *mpm_config_va;
+ struct dma_iommu_mapping *smmu_mapping;
+ dma_addr_t smmu_iova_start;
+ size_t smmu_iova_len;
+ struct clk *smmu_clk;
struct qmi_handle *wlfw_clnt;
struct list_head qmi_event_list;
spinlock_t qmi_event_lock;
@@ -1170,9 +1178,120 @@ static ssize_t icnss_wlan_mode_store(struct device *dev,
static DEVICE_ATTR(icnss_wlan_mode, S_IWUSR, NULL, icnss_wlan_mode_store);
+static struct clk *icnss_clock_init(struct device *dev, const char *cname)
+{
+ struct clk *c;
+ long rate;
+
+ if (of_property_match_string(dev->of_node, "clock-names", cname) < 0) {
+ pr_err("%s: clock %s is not found!", __func__, cname);
+ return NULL;
+ }
+
+ c = devm_clk_get(dev, cname);
+ if (IS_ERR(c)) {
+ pr_err("%s: couldn't get clock %s!", __func__, cname);
+ return NULL;
+ }
+
+ if (clk_get_rate(c) == 0) {
+ rate = clk_round_rate(c, 1000);
+ clk_set_rate(c, rate);
+ }
+
+ return c;
+}
+
+static int icnss_clock_enable(struct clk *c)
+{
+ int ret = 0;
+
+ ret = clk_prepare_enable(c);
+
+ if (ret < 0)
+ pr_err("%s: couldn't enable clock!\n", __func__);
+
+ return ret;
+}
+
+static void icnss_clock_disable(struct clk *c)
+{
+ clk_disable_unprepare(c);
+}
+
+static int icnss_smmu_init(struct device *dev)
+{
+ struct dma_iommu_mapping *mapping;
+ int disable_htw = 1;
+ int atomic_ctx = 1;
+ int s1_bypass = 1;
+ int ret = 0;
+
+ mapping = arm_iommu_create_mapping(&platform_bus_type,
+ penv->smmu_iova_start,
+ penv->smmu_iova_len);
+ if (IS_ERR(mapping)) {
+ pr_err("%s: create mapping failed, err = %d\n", __func__, ret);
+ ret = PTR_ERR(mapping);
+ goto map_fail;
+ }
+
+ ret = iommu_domain_set_attr(mapping->domain,
+ DOMAIN_ATTR_COHERENT_HTW_DISABLE,
+ &disable_htw);
+ if (ret < 0) {
+ pr_err("%s: set disable_htw attribute failed, err = %d\n",
+ __func__, ret);
+ goto set_attr_fail;
+ }
+
+ ret = iommu_domain_set_attr(mapping->domain,
+ DOMAIN_ATTR_ATOMIC,
+ &atomic_ctx);
+ if (ret < 0) {
+ pr_err("%s: set atomic_ctx attribute failed, err = %d\n",
+ __func__, ret);
+ goto set_attr_fail;
+ }
+
+ ret = iommu_domain_set_attr(mapping->domain,
+ DOMAIN_ATTR_S1_BYPASS,
+ &s1_bypass);
+ if (ret < 0) {
+ pr_err("%s: set s1_bypass attribute failed, err = %d\n",
+ __func__, ret);
+ goto set_attr_fail;
+ }
+
+ ret = arm_iommu_attach_device(dev, mapping);
+ if (ret < 0) {
+ pr_err("%s: attach device failed, err = %d\n", __func__, ret);
+ goto attach_fail;
+ }
+
+ penv->smmu_mapping = mapping;
+
+ return ret;
+
+attach_fail:
+set_attr_fail:
+ arm_iommu_release_mapping(mapping);
+map_fail:
+ return ret;
+}
+
+static void icnss_smmu_remove(struct device *dev)
+{
+ arm_iommu_detach_device(dev);
+ arm_iommu_release_mapping(penv->smmu_mapping);
+
+ penv->smmu_mapping = NULL;
+}
+
static int icnss_probe(struct platform_device *pdev)
{
int ret = 0;
+ u32 smmu_iova_address[2];
struct resource *res;
int i;
struct device *dev = &pdev->dev;
@@ -1247,6 +1366,30 @@ static int icnss_probe(struct platform_device *pdev)
goto unmap_mpm_config;
}
+ if (of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,wlan-smmu-iova-address",
+ smmu_iova_address, 2) == 0) {
+ penv->smmu_iova_start = smmu_iova_address[0];
+ penv->smmu_iova_len = smmu_iova_address[1];
+
+ ret = icnss_smmu_init(&pdev->dev);
+ if (ret < 0) {
+ pr_err("%s: SMMU init failed, err = %d\n",
+ __func__, ret);
+ goto err_smmu_init;
+ }
+
+ penv->smmu_clk = icnss_clock_init(&pdev->dev, SMMU_CLOCK_NAME);
+ if (penv->smmu_clk) {
+ ret = icnss_clock_enable(penv->smmu_clk);
+ if (ret < 0) {
+ pr_err("%s: SMMU clock enable failed!\n",
+ __func__);
+ goto err_smmu_clock_enable;
+ }
+ }
+ }
+
penv->skip_qmi = of_property_read_bool(dev->of_node,
"qcom,skip-qmi");
@@ -1289,6 +1432,12 @@ err_qmi:
err_workqueue:
device_remove_file(&pdev->dev, &dev_attr_icnss_wlan_mode);
err_wlan_mode:
+ if (penv->smmu_clk)
+ icnss_clock_disable(penv->smmu_clk);
+err_smmu_clock_enable:
+ if (penv->smmu_mapping)
+ icnss_smmu_remove(&pdev->dev);
+err_smmu_init:
if (penv->msa_va)
dma_free_coherent(&pdev->dev, penv->msa_mem_size,
penv->msa_va, penv->msa_pa);
@@ -1311,6 +1460,13 @@ static int icnss_remove(struct platform_device *pdev)
if (penv->qmi_event_wq)
destroy_workqueue(penv->qmi_event_wq);
device_remove_file(&pdev->dev, &dev_attr_icnss_wlan_mode);
+
+ if (penv->smmu_mapping) {
+ if (penv->smmu_clk)
+ icnss_clock_disable(penv->smmu_clk);
+ icnss_smmu_remove(&pdev->dev);
+ }
+
if (penv->msa_va)
dma_free_coherent(&pdev->dev, penv->msa_mem_size,
penv->msa_va, penv->msa_pa);
diff --git a/drivers/soc/qcom/rpm_log.c b/drivers/soc/qcom/rpm_log.c
new file mode 100644
index 000000000000..deea77c6b0a9
--- /dev/null
+++ b/drivers/soc/qcom/rpm_log.c
@@ -0,0 +1,549 @@
+/* Copyright (c) 2010-2011, 2013-2014, The Linux Foundation.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+#include "rpm_log.h"
+
+/* registers in MSM_RPM_LOG_PAGE_INDICES */
+enum {
+ MSM_RPM_LOG_TAIL,
+ MSM_RPM_LOG_HEAD
+};
+
+/* used to 4 byte align message lengths */
+#define PADDED_LENGTH(x) (0xFFFFFFFC & ((x) + 3))
+
+/* calculates the character string length of a message of byte length x */
+#define PRINTED_LENGTH(x) ((x) * 6 + 3)
+
+/* number of ms to wait between checking for new messages in the RPM log */
+#define RECHECK_TIME (50)
+
+#define VERSION_8974 0x1000
+#define RPM_ULOG_LENGTH_SHIFT 16
+#define RPM_ULOG_LENGTH_MASK 0xFFFF0000
+
+struct msm_rpm_log_buffer {
+ char *data;
+ u32 len;
+ u32 pos;
+ struct mutex mutex;
+ u32 max_len;
+ u32 read_idx;
+ struct msm_rpm_log_platform_data *pdata;
+};
+
+/******************************************************************************
+ * Internal functions
+ *****************************************************************************/
+
+static inline u32
+msm_rpm_log_read(const struct msm_rpm_log_platform_data *pdata, u32 page,
+ u32 reg)
+{
+ return readl_relaxed(pdata->reg_base + pdata->reg_offsets[page]
+ + reg * 4);
+}
+
+/*
+ * msm_rpm_log_copy() - Copies messages from a volatile circular buffer in
+ * the RPM's shared memory into a private local buffer
+ * msg_buffer: pointer to local buffer (string)
+ * buf_len: length of local buffer in bytes
+ * read_start_idx: index into shared memory buffer
+ *
+ * Return value: number of bytes written to the local buffer
+ *
+ * Copies messages stored in a circular buffer in the RPM Message Memory into
+ * a specified local buffer. The RPM processor is unaware of these reading
+ * efforts, so care is taken to make sure that messages are valid both before
+ * and after reading. The RPM processor utilizes a ULog driver to write the
+ * log. The RPM processor maintains tail and head indices. These correspond
+ * to the next byte to write into, and the first valid byte, respectively.
+ * Both indices increase monotonically (except for rollover).
+ *
+ * Messages take the form of [(u32)length] [(char)data0,1,...] in which the
+ * length specifies the number of payload bytes. Messages must be 4 byte
+ * aligned, so padding is added at the end of a message as needed.
+ *
+ * Print format:
+ * - 0xXX, 0xXX, 0xXX
+ * - 0xXX
+ * etc...
+ */
+static u32 msm_rpm_log_copy(const struct msm_rpm_log_platform_data *pdata,
+ char *msg_buffer, u32 buf_len, u32 *read_idx)
+{
+ u32 head_idx, tail_idx;
+ u32 pos = 0;
+ u32 i = 0;
+ u32 msg_len;
+ u32 pos_start;
+ char temp[4];
+
+ tail_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES,
+ MSM_RPM_LOG_TAIL);
+ head_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES,
+ MSM_RPM_LOG_HEAD);
+
+ /* loop while the remote buffer has valid messages left to read */
+ while (tail_idx - head_idx > 0 && tail_idx - *read_idx > 0) {
+ head_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES,
+ MSM_RPM_LOG_HEAD);
+ tail_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES,
+ MSM_RPM_LOG_TAIL);
+ /* check if the message to be read is valid */
+ if (tail_idx - *read_idx > tail_idx - head_idx) {
+ *read_idx = head_idx;
+ continue;
+ }
+
+ /*
+ * Ensure that all indices are 4 byte aligned.
+ * This conditions is required to interact with a ULog buffer
+ * properly.
+ */
+ if (!IS_ALIGNED((tail_idx | head_idx | *read_idx), 4))
+ break;
+
+ msg_len = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_BUFFER,
+ ((*read_idx) & pdata->log_len_mask) >> 2);
+
+ /* Message length for 8974 is first 2 bytes.
+ * Exclude message length and format from message length.
+ */
+ if (pdata->version == VERSION_8974) {
+ msg_len = (msg_len & RPM_ULOG_LENGTH_MASK) >>
+ RPM_ULOG_LENGTH_SHIFT;
+ msg_len -= 4;
+ }
+
+ /* handle messages that claim to be longer than the log */
+ if (PADDED_LENGTH(msg_len) > tail_idx - *read_idx - 4)
+ msg_len = tail_idx - *read_idx - 4;
+
+ /* check that the local buffer has enough space for this msg */
+ if (pos + PRINTED_LENGTH(msg_len) > buf_len)
+ break;
+
+ pos_start = pos;
+ pos += scnprintf(msg_buffer + pos, buf_len - pos, "- ");
+
+ /* copy message payload to local buffer */
+ for (i = 0; i < msg_len; i++) {
+ /* read from shared memory 4 bytes at a time */
+ if (IS_ALIGNED(i, 4))
+ *((u32 *)temp) = msm_rpm_log_read(pdata,
+ MSM_RPM_LOG_PAGE_BUFFER,
+ ((*read_idx + 4 + i) &
+ pdata->log_len_mask) >> 2);
+
+ pos += scnprintf(msg_buffer + pos, buf_len - pos,
+ "0x%02X, ", temp[i & 0x03]);
+ }
+
+ pos += scnprintf(msg_buffer + pos, buf_len - pos, "\n");
+
+ head_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES,
+ MSM_RPM_LOG_HEAD);
+ tail_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES,
+ MSM_RPM_LOG_TAIL);
+
+ /* roll back if message that was read is not still valid */
+ if (tail_idx - *read_idx > tail_idx - head_idx)
+ pos = pos_start;
+
+ *read_idx += PADDED_LENGTH(msg_len) + 4;
+ }
+
+ return pos;
+}
+
+
+/*
+ * msm_rpm_log_file_read() - Reads in log buffer messages then outputs them to a
+ * user buffer
+ *
+ * Return value:
+ * 0: success
+ * -ENOMEM: no memory available
+ * -EINVAL: user buffer null or requested bytes 0
+ * -EFAULT: user buffer not writeable
+ * -EAGAIN: no bytes available at the moment
+ */
+static ssize_t msm_rpm_log_file_read(struct file *file, char __user *bufu,
+ size_t count, loff_t *ppos)
+{
+ u32 out_len, remaining;
+ struct msm_rpm_log_platform_data *pdata;
+ struct msm_rpm_log_buffer *buf;
+
+ buf = file->private_data;
+
+ if (!buf)
+ return -ENOMEM;
+
+ pdata = buf->pdata;
+
+ if (!pdata)
+ return -EINVAL;
+ if (!buf->data)
+ return -ENOMEM;
+ if (!bufu || count == 0)
+ return -EINVAL;
+ if (!access_ok(VERIFY_WRITE, bufu, count))
+ return -EFAULT;
+
+ mutex_lock(&buf->mutex);
+ /* check for more messages if local buffer empty */
+ if (buf->pos == buf->len) {
+ buf->pos = 0;
+ buf->len = msm_rpm_log_copy(pdata, buf->data, buf->max_len,
+ &(buf->read_idx));
+ }
+
+ if ((file->f_flags & O_NONBLOCK) && buf->len == 0) {
+ mutex_unlock(&buf->mutex);
+ return -EAGAIN;
+ }
+
+ /* loop until new messages arrive */
+ while (buf->len == 0) {
+ cond_resched();
+ if (msleep_interruptible(RECHECK_TIME))
+ break;
+ buf->len = msm_rpm_log_copy(pdata, buf->data, buf->max_len,
+ &(buf->read_idx));
+ }
+
+ out_len = ((buf->len - buf->pos) < count ? buf->len - buf->pos : count);
+
+ remaining = __copy_to_user(bufu, &(buf->data[buf->pos]), out_len);
+ buf->pos += out_len - remaining;
+ mutex_unlock(&buf->mutex);
+
+ return out_len - remaining;
+}
+
+
+/*
+ * msm_rpm_log_file_open() - Allows a new reader to open the RPM log virtual
+ * file
+ *
+ * One local buffer is kmalloc'ed for each reader, so no resource sharing has
+ * to take place (besides the read only access to the RPM log buffer).
+ *
+ * Return value:
+ * 0: success
+ * -ENOMEM: no memory available
+ */
+static int msm_rpm_log_file_open(struct inode *inode, struct file *file)
+{
+ struct msm_rpm_log_buffer *buf;
+ struct msm_rpm_log_platform_data *pdata;
+
+ pdata = inode->i_private;
+ if (!pdata)
+ return -EINVAL;
+
+ file->private_data =
+ kmalloc(sizeof(struct msm_rpm_log_buffer), GFP_KERNEL);
+ if (!file->private_data) {
+ pr_err("%s: ERROR kmalloc failed to allocate %zu bytes\n",
+ __func__, sizeof(struct msm_rpm_log_buffer));
+ return -ENOMEM;
+ }
+ buf = file->private_data;
+
+ buf->data = kmalloc(PRINTED_LENGTH(pdata->log_len), GFP_KERNEL);
+ if (!buf->data) {
+ kfree(file->private_data);
+ file->private_data = NULL;
+ pr_err("%s: ERROR kmalloc failed to allocate %d bytes\n",
+ __func__, PRINTED_LENGTH(pdata->log_len));
+ return -ENOMEM;
+ }
+
+ buf->pdata = pdata;
+ buf->len = 0;
+ buf->pos = 0;
+ mutex_init(&buf->mutex);
+ buf->max_len = PRINTED_LENGTH(pdata->log_len);
+ buf->read_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES,
+ MSM_RPM_LOG_HEAD);
+ return 0;
+}
+
+static int msm_rpm_log_file_close(struct inode *inode, struct file *file)
+{
+ kfree(((struct msm_rpm_log_buffer *)file->private_data)->data);
+ kfree(file->private_data);
+ return 0;
+}
+
+
+static const struct file_operations msm_rpm_log_file_fops = {
+ .owner = THIS_MODULE,
+ .open = msm_rpm_log_file_open,
+ .read = msm_rpm_log_file_read,
+ .release = msm_rpm_log_file_close,
+};
+
+static int msm_rpm_log_probe(struct platform_device *pdev)
+{
+ struct dentry *dent;
+ struct msm_rpm_log_platform_data *pdata;
+ struct resource *res = NULL, *offset = NULL;
+ struct device_node *node = NULL;
+ phys_addr_t page_buffer_address, rpm_addr_phys;
+ int ret = 0;
+ char *key = NULL;
+ uint32_t val = 0;
+ uint32_t offset_addr = 0;
+ void __iomem *phys_ptr = NULL;
+
+ node = pdev->dev.of_node;
+
+ if (node) {
+ pdata = kzalloc(sizeof(struct msm_rpm_log_platform_data),
+ GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ pr_err("%s: could not get resource\n", __func__);
+ kfree(pdata);
+ return -EINVAL;
+ }
+
+ offset = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (offset) {
+ /* Remap the rpm-log pointer */
+ phys_ptr = ioremap_nocache(offset->start, SZ_4);
+ if (!phys_ptr) {
+ pr_err("%s: Failed to ioremap address: %x\n",
+ __func__, offset_addr);
+ return -ENODEV;
+ }
+ offset_addr = readl_relaxed(phys_ptr);
+ iounmap(phys_ptr);
+ }
+
+ pdata->phys_addr_base = res->start + offset_addr;
+ pdata->phys_size = resource_size(res);
+
+ pdata->reg_base = ioremap_nocache(pdata->phys_addr_base,
+ pdata->phys_size);
+ if (!pdata->reg_base) {
+ pr_err("%s: ERROR could not ioremap: start=%pa, len=%u\n",
+ __func__, &pdata->phys_addr_base,
+ pdata->phys_size);
+ kfree(pdata);
+ return -EBUSY;
+ }
+ /* Read various parameters from the header if the
+ * version of the RPM Ulog is 0x1000. This version
+ * corresponds to the node in the rpm header which
+ * holds RPM log on 8974.
+ *
+ * offset-page-buffer-addr: At this offset header
+ * contains address of the location where raw log
+ * starts
+ * offset-log-len: At this offset header contains
+ * the length of the log buffer.
+ * offset-log-len-mask: At this offset header contains
+ * the log length mask for the buffer.
+ * offset-page-indices: At this offset header contains
+ * the index for writer.
+ */
+
+ key = "qcom,offset-version";
+ ret = of_property_read_u32(node, key, &val);
+ if (ret) {
+ pr_err("%s: Error in name %s key %s\n",
+ __func__, node->full_name, key);
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ pdata->version = readl_relaxed(pdata->reg_base + val);
+ if (pdata->version == VERSION_8974) {
+ key = "qcom,rpm-addr-phys";
+ ret = of_property_read_u32(node, key, &val);
+ if (ret) {
+ pr_err("%s: Error in name %s key %s\n",
+ __func__, node->full_name, key);
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ rpm_addr_phys = val;
+
+ key = "qcom,offset-page-buffer-addr";
+ ret = of_property_read_u32(node, key, &val);
+ if (ret) {
+ pr_err("%s: Error in name %s key %s\n",
+ __func__, node->full_name, key);
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ page_buffer_address = rpm_addr_phys +
+ readl_relaxed(pdata->reg_base + val);
+ pdata->reg_offsets[MSM_RPM_LOG_PAGE_BUFFER] =
+ page_buffer_address - pdata->phys_addr_base;
+
+ key = "qcom,offset-log-len";
+ ret = of_property_read_u32(node, key, &val);
+ if (ret) {
+ pr_err("%s: Error in name %s key %s\n",
+ __func__, node->full_name, key);
+ ret = -EFAULT;
+ goto fail;
+ }
+ pdata->log_len = readl_relaxed(pdata->reg_base + val);
+
+ if (pdata->log_len > pdata->phys_size) {
+ pr_err("%s: Error phy size: %d should be atleast log length: %d\n",
+ __func__, pdata->phys_size,
+ pdata->log_len);
+
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ key = "qcom,offset-log-len-mask";
+ ret = of_property_read_u32(node, key, &val);
+ if (ret) {
+ pr_err("%s: Error in name %s key %s\n",
+ __func__, node->full_name, key);
+ ret = -EFAULT;
+ goto fail;
+ }
+ pdata->log_len_mask = readl_relaxed(pdata->reg_base
+ + val);
+
+ key = "qcom,offset-page-indices";
+ ret = of_property_read_u32(node, key, &val);
+ if (ret) {
+ pr_err("%s: Error in name %s key %s\n",
+ __func__, node->full_name, key);
+ ret = -EFAULT;
+ goto fail;
+ }
+ pdata->reg_offsets[MSM_RPM_LOG_PAGE_INDICES] =
+ val;
+ } else{
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ } else{
+ pdata = pdev->dev.platform_data;
+ if (!pdata)
+ return -EINVAL;
+
+ pdata->reg_base = ioremap(pdata->phys_addr_base,
+ pdata->phys_size);
+ if (!pdata->reg_base) {
+ pr_err("%s: ERROR could not ioremap: start=%pa, len=%u\n",
+ __func__, &pdata->phys_addr_base,
+ pdata->phys_size);
+ return -EBUSY;
+ }
+ }
+
+ dent = debugfs_create_file("rpm_log", S_IRUGO, NULL,
+ pdata, &msm_rpm_log_file_fops);
+ if (!dent) {
+ pr_err("%s: ERROR debugfs_create_file failed\n", __func__);
+ if (pdata->version == VERSION_8974) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, dent);
+
+ pr_notice("%s: OK\n", __func__);
+ return 0;
+
+fail:
+ iounmap(pdata->reg_base);
+ kfree(pdata);
+ return ret;
+}
+
+static int msm_rpm_log_remove(struct platform_device *pdev)
+{
+ struct dentry *dent;
+ struct msm_rpm_log_platform_data *pdata;
+
+ pdata = pdev->dev.platform_data;
+
+ iounmap(pdata->reg_base);
+
+ dent = platform_get_drvdata(pdev);
+ debugfs_remove(dent);
+ platform_set_drvdata(pdev, NULL);
+
+ pr_notice("%s: OK\n", __func__);
+ return 0;
+}
+
+static const struct of_device_id rpm_log_table[] = {
+ {.compatible = "qcom,rpm-log"},
+ {},
+};
+
+static struct platform_driver msm_rpm_log_driver = {
+ .probe = msm_rpm_log_probe,
+ .remove = msm_rpm_log_remove,
+ .driver = {
+ .name = "msm_rpm_log",
+ .owner = THIS_MODULE,
+ .of_match_table = rpm_log_table,
+ },
+};
+
+static int __init msm_rpm_log_init(void)
+{
+ return platform_driver_register(&msm_rpm_log_driver);
+}
+
+static void __exit msm_rpm_log_exit(void)
+{
+ platform_driver_unregister(&msm_rpm_log_driver);
+}
+
+module_init(msm_rpm_log_init);
+module_exit(msm_rpm_log_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM RPM Log driver");
+MODULE_ALIAS("platform:msm_rpm_log");
diff --git a/drivers/soc/qcom/rpm_log.h b/drivers/soc/qcom/rpm_log.h
new file mode 100644
index 000000000000..1f1a9f78f37f
--- /dev/null
+++ b/drivers/soc/qcom/rpm_log.h
@@ -0,0 +1,35 @@
+/* Copyright (c) 2010, 2013, 2016 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_RPM_LOG_H
+#define __ARCH_ARM_MACH_MSM_RPM_LOG_H
+
+#include <linux/types.h>
+
+enum {
+ MSM_RPM_LOG_PAGE_INDICES,
+ MSM_RPM_LOG_PAGE_BUFFER,
+ MSM_RPM_LOG_PAGE_COUNT
+};
+
+struct msm_rpm_log_platform_data {
+ u32 reg_offsets[MSM_RPM_LOG_PAGE_COUNT];
+ u32 log_len;
+ u32 log_len_mask;
+ phys_addr_t phys_addr_base;
+ u32 phys_size;
+ u32 version;
+ void __iomem *reg_base;
+};
+
+#endif /* __ARCH_ARM_MACH_MSM_RPM_LOG_H */
diff --git a/drivers/soc/qcom/rpm_master_stat.c b/drivers/soc/qcom/rpm_master_stat.c
new file mode 100644
index 000000000000..14004a2b721e
--- /dev/null
+++ b/drivers/soc/qcom/rpm_master_stat.c
@@ -0,0 +1,473 @@
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/of.h>
+#include <linux/uaccess.h>
+
+#include "rpm_stats.h"
+
+#define RPM_MASTERS_BUF_LEN 400
+
+#define SNPRINTF(buf, size, format, ...) \
+ do { \
+ if (size > 0) { \
+ int ret; \
+ ret = snprintf(buf, size, format, ## __VA_ARGS__); \
+ if (ret > size) { \
+ buf += size; \
+ size = 0; \
+ } else { \
+ buf += ret; \
+ size -= ret; \
+ } \
+ } \
+ } while (0)
+
+#define GET_MASTER_NAME(a, prvdata) \
+ ((a >= prvdata->num_masters) ? "Invalid Master Name" : \
+ prvdata->master_names[a])
+
+#define GET_FIELD(a) ((strnstr(#a, ".", 80) + 1))
+
+struct msm_rpm_master_stats {
+ uint32_t active_cores;
+ uint32_t numshutdowns;
+ uint64_t shutdown_req;
+ uint64_t wakeup_ind;
+ uint64_t bringup_req;
+ uint64_t bringup_ack;
+ uint32_t wakeup_reason; /* 0 = rude wakeup, 1 = scheduled wakeup */
+ uint32_t last_sleep_transition_duration;
+ uint32_t last_wake_transition_duration;
+ uint32_t xo_count;
+ uint64_t xo_last_entered_at;
+ uint64_t xo_last_exited_at;
+ uint64_t xo_accumulated_duration;
+};
+
+struct msm_rpm_master_stats_private_data {
+ void __iomem *reg_base;
+ u32 len;
+ char **master_names;
+ u32 num_masters;
+ char buf[RPM_MASTERS_BUF_LEN];
+ struct msm_rpm_master_stats_platform_data *platform_data;
+};
+
+int msm_rpm_master_stats_file_close(struct inode *inode,
+ struct file *file)
+{
+ struct msm_rpm_master_stats_private_data *private = file->private_data;
+
+ if (private->reg_base)
+ iounmap(private->reg_base);
+ kfree(file->private_data);
+
+ return 0;
+}
+
+static int msm_rpm_master_copy_stats(
+ struct msm_rpm_master_stats_private_data *prvdata)
+{
+ struct msm_rpm_master_stats record;
+ struct msm_rpm_master_stats_platform_data *pdata;
+ static int master_cnt;
+ int count, j = 0;
+ char *buf;
+ static DEFINE_MUTEX(msm_rpm_master_stats_mutex);
+
+ mutex_lock(&msm_rpm_master_stats_mutex);
+
+ /* Iterate possible number of masters */
+ if (master_cnt > prvdata->num_masters - 1) {
+ master_cnt = 0;
+ mutex_unlock(&msm_rpm_master_stats_mutex);
+ return 0;
+ }
+
+ pdata = prvdata->platform_data;
+ count = RPM_MASTERS_BUF_LEN;
+ buf = prvdata->buf;
+
+ if (prvdata->platform_data->version == 2) {
+ SNPRINTF(buf, count, "%s\n",
+ GET_MASTER_NAME(master_cnt, prvdata));
+
+ record.shutdown_req = readq_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats, shutdown_req)));
+
+ SNPRINTF(buf, count, "\t%s:0x%llX\n",
+ GET_FIELD(record.shutdown_req),
+ record.shutdown_req);
+
+ record.wakeup_ind = readq_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats, wakeup_ind)));
+
+ SNPRINTF(buf, count, "\t%s:0x%llX\n",
+ GET_FIELD(record.wakeup_ind),
+ record.wakeup_ind);
+
+ record.bringup_req = readq_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats, bringup_req)));
+
+ SNPRINTF(buf, count, "\t%s:0x%llX\n",
+ GET_FIELD(record.bringup_req),
+ record.bringup_req);
+
+ record.bringup_ack = readq_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats, bringup_ack)));
+
+ SNPRINTF(buf, count, "\t%s:0x%llX\n",
+ GET_FIELD(record.bringup_ack),
+ record.bringup_ack);
+
+ record.xo_last_entered_at = readq_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats,
+ xo_last_entered_at)));
+
+ SNPRINTF(buf, count, "\t%s:0x%llX\n",
+ GET_FIELD(record.xo_last_entered_at),
+ record.xo_last_entered_at);
+
+ record.xo_last_exited_at = readq_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats,
+ xo_last_exited_at)));
+
+ SNPRINTF(buf, count, "\t%s:0x%llX\n",
+ GET_FIELD(record.xo_last_exited_at),
+ record.xo_last_exited_at);
+
+ record.xo_accumulated_duration =
+ readq_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats,
+ xo_accumulated_duration)));
+
+ SNPRINTF(buf, count, "\t%s:0x%llX\n",
+ GET_FIELD(record.xo_accumulated_duration),
+ record.xo_accumulated_duration);
+
+ record.last_sleep_transition_duration =
+ readl_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats,
+ last_sleep_transition_duration)));
+
+ SNPRINTF(buf, count, "\t%s:0x%x\n",
+ GET_FIELD(record.last_sleep_transition_duration),
+ record.last_sleep_transition_duration);
+
+ record.last_wake_transition_duration =
+ readl_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats,
+ last_wake_transition_duration)));
+
+ SNPRINTF(buf, count, "\t%s:0x%x\n",
+ GET_FIELD(record.last_wake_transition_duration),
+ record.last_wake_transition_duration);
+
+ record.xo_count =
+ readl_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats,
+ xo_count)));
+
+ SNPRINTF(buf, count, "\t%s:0x%x\n",
+ GET_FIELD(record.xo_count),
+ record.xo_count);
+
+ record.wakeup_reason = readl_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats,
+ wakeup_reason)));
+
+ SNPRINTF(buf, count, "\t%s:0x%x\n",
+ GET_FIELD(record.wakeup_reason),
+ record.wakeup_reason);
+
+ record.numshutdowns = readl_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset +
+ offsetof(struct msm_rpm_master_stats, numshutdowns)));
+
+ SNPRINTF(buf, count, "\t%s:0x%x\n",
+ GET_FIELD(record.numshutdowns),
+ record.numshutdowns);
+
+ record.active_cores = readl_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset) +
+ offsetof(struct msm_rpm_master_stats, active_cores));
+
+ SNPRINTF(buf, count, "\t%s:0x%x\n",
+ GET_FIELD(record.active_cores),
+ record.active_cores);
+ } else {
+ SNPRINTF(buf, count, "%s\n",
+ GET_MASTER_NAME(master_cnt, prvdata));
+
+ record.numshutdowns = readl_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset) + 0x0);
+
+ SNPRINTF(buf, count, "\t%s:0x%0x\n",
+ GET_FIELD(record.numshutdowns),
+ record.numshutdowns);
+
+ record.active_cores = readl_relaxed(prvdata->reg_base +
+ (master_cnt * pdata->master_offset) + 0x4);
+
+ SNPRINTF(buf, count, "\t%s:0x%0x\n",
+ GET_FIELD(record.active_cores),
+ record.active_cores);
+ }
+
+ j = find_first_bit((unsigned long *)&record.active_cores,
+ BITS_PER_LONG);
+ while (j < BITS_PER_LONG) {
+ SNPRINTF(buf, count, "\t\tcore%d\n", j);
+ j = find_next_bit((unsigned long *)&record.active_cores,
+ BITS_PER_LONG, j + 1);
+ }
+
+ master_cnt++;
+ mutex_unlock(&msm_rpm_master_stats_mutex);
+ return RPM_MASTERS_BUF_LEN - count;
+}
+
+static ssize_t msm_rpm_master_stats_file_read(struct file *file,
+ char __user *bufu, size_t count, loff_t *ppos)
+{
+ struct msm_rpm_master_stats_private_data *prvdata;
+ struct msm_rpm_master_stats_platform_data *pdata;
+
+ prvdata = file->private_data;
+ if (!prvdata)
+ return -EINVAL;
+
+ pdata = prvdata->platform_data;
+ if (!pdata)
+ return -EINVAL;
+
+ if (!bufu || count == 0)
+ return -EINVAL;
+
+ if (*ppos <= pdata->phys_size) {
+ prvdata->len = msm_rpm_master_copy_stats(prvdata);
+ *ppos = 0;
+ }
+
+ return simple_read_from_buffer(bufu, count, ppos,
+ prvdata->buf, prvdata->len);
+}
+
+static int msm_rpm_master_stats_file_open(struct inode *inode,
+ struct file *file)
+{
+ struct msm_rpm_master_stats_private_data *prvdata;
+ struct msm_rpm_master_stats_platform_data *pdata;
+
+ pdata = inode->i_private;
+
+ file->private_data =
+ kzalloc(sizeof(struct msm_rpm_master_stats_private_data),
+ GFP_KERNEL);
+
+ if (!file->private_data)
+ return -ENOMEM;
+ prvdata = file->private_data;
+
+ prvdata->reg_base = ioremap(pdata->phys_addr_base,
+ pdata->phys_size);
+ if (!prvdata->reg_base) {
+ kfree(file->private_data);
+ prvdata = NULL;
+ pr_err("%s: ERROR could not ioremap start=%pa, len=%u\n",
+ __func__, &pdata->phys_addr_base,
+ pdata->phys_size);
+ return -EBUSY;
+ }
+
+ prvdata->len = 0;
+ prvdata->num_masters = pdata->num_masters;
+ prvdata->master_names = pdata->masters;
+ prvdata->platform_data = pdata;
+ return 0;
+}
+
+static const struct file_operations msm_rpm_master_stats_fops = {
+ .owner = THIS_MODULE,
+ .open = msm_rpm_master_stats_file_open,
+ .read = msm_rpm_master_stats_file_read,
+ .release = msm_rpm_master_stats_file_close,
+ .llseek = no_llseek,
+};
+
+static struct msm_rpm_master_stats_platform_data
+ *msm_rpm_master_populate_pdata(struct device *dev)
+{
+ struct msm_rpm_master_stats_platform_data *pdata;
+ struct device_node *node = dev->of_node;
+ int rc = 0, i;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ goto err;
+
+ rc = of_property_read_u32(node, "qcom,master-stats-version",
+ &pdata->version);
+ if (rc) {
+ dev_err(dev, "master-stats-version missing rc=%d\n", rc);
+ goto err;
+ }
+
+ rc = of_property_read_u32(node, "qcom,master-offset",
+ &pdata->master_offset);
+ if (rc) {
+ dev_err(dev, "master-offset missing rc=%d\n", rc);
+ goto err;
+ }
+
+ pdata->num_masters = of_property_count_strings(node, "qcom,masters");
+ if (pdata->num_masters < 0) {
+ dev_err(dev, "Failed to get number of masters =%d\n",
+ pdata->num_masters);
+ goto err;
+ }
+
+ pdata->masters = devm_kzalloc(dev, sizeof(char *) * pdata->num_masters,
+ GFP_KERNEL);
+ if (!pdata->masters)
+ goto err;
+
+ /*
+ * Read master names from DT
+ */
+ for (i = 0; i < pdata->num_masters; i++) {
+ const char *master_name;
+
+ of_property_read_string_index(node, "qcom,masters",
+ i, &master_name);
+ pdata->masters[i] = devm_kzalloc(dev, sizeof(char) *
+ strlen(master_name) + 1, GFP_KERNEL);
+ if (!pdata->masters[i])
+ goto err;
+
+ strlcpy(pdata->masters[i], master_name,
+ strlen(master_name) + 1);
+ }
+ return pdata;
+err:
+ return NULL;
+}
+
+static int msm_rpm_master_stats_probe(struct platform_device *pdev)
+{
+ struct dentry *dent;
+ struct msm_rpm_master_stats_platform_data *pdata;
+ struct resource *res = NULL;
+
+ if (!pdev)
+ return -EINVAL;
+
+ if (pdev->dev.of_node)
+ pdata = msm_rpm_master_populate_pdata(&pdev->dev);
+ else
+ pdata = pdev->dev.platform_data;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "%s: Unable to get pdata\n", __func__);
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res) {
+ dev_err(&pdev->dev,
+ "%s: Failed to get IO resource from platform device",
+ __func__);
+ return -ENXIO;
+ }
+
+ pdata->phys_addr_base = res->start;
+ pdata->phys_size = resource_size(res);
+
+ dent = debugfs_create_file("rpm_master_stats", S_IRUGO, NULL,
+ pdata, &msm_rpm_master_stats_fops);
+
+ if (!dent) {
+ dev_err(&pdev->dev, "%s: ERROR debugfs_create_file failed\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, dent);
+ return 0;
+}
+
+static int msm_rpm_master_stats_remove(struct platform_device *pdev)
+{
+ struct dentry *dent;
+
+ dent = platform_get_drvdata(pdev);
+ debugfs_remove(dent);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+static const struct of_device_id rpm_master_table[] = {
+ {.compatible = "qcom,rpm-master-stats"},
+ {},
+};
+
+static struct platform_driver msm_rpm_master_stats_driver = {
+ .probe = msm_rpm_master_stats_probe,
+ .remove = msm_rpm_master_stats_remove,
+ .driver = {
+ .name = "msm_rpm_master_stats",
+ .owner = THIS_MODULE,
+ .of_match_table = rpm_master_table,
+ },
+};
+
+static int __init msm_rpm_master_stats_init(void)
+{
+ return platform_driver_register(&msm_rpm_master_stats_driver);
+}
+
+static void __exit msm_rpm_master_stats_exit(void)
+{
+ platform_driver_unregister(&msm_rpm_master_stats_driver);
+}
+
+module_init(msm_rpm_master_stats_init);
+module_exit(msm_rpm_master_stats_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM RPM Master Statistics driver");
+MODULE_ALIAS("platform:msm_master_stat_log");
diff --git a/drivers/soc/qcom/rpm_rbcpr_stats_v2.c b/drivers/soc/qcom/rpm_rbcpr_stats_v2.c
new file mode 100644
index 000000000000..2a8d0e5fe095
--- /dev/null
+++ b/drivers/soc/qcom/rpm_rbcpr_stats_v2.c
@@ -0,0 +1,421 @@
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/sort.h>
+#include <linux/uaccess.h>
+
+#define RBCPR_BUF_LEN 8000
+#define RBCPR_STATS_MAX_SIZE SZ_2K
+#define RBCPR_MAX_RAILS 4
+#define RBCPR_NUM_RECMNDS 3
+#define RBCPR_NUM_CORNERS 3
+
+#define FIELD(a) ((strnstr(#a, "->", 80) + 2))
+#define PRINT(buf, pos, format, ...) \
+ ((pos < RBCPR_BUF_LEN) ? snprintf((buf + pos), (RBCPR_BUF_LEN - pos),\
+ format, ## __VA_ARGS__) : 0)
+
+enum {
+ CORNER_OFF,
+ CORNER_RETENTION,
+ CORNER_SVS_KRAIT,
+ CORNER_SVS_SOC,
+ CORNER_NOMINAL,
+ CORNER_TURBO,
+ CORNER_SUPER_TURBO,
+ CORNER_MAX,
+};
+
+struct rbcpr_recmnd_data_type {
+ uint32_t microvolts;
+ uint64_t timestamp;
+};
+
+struct rbcpr_corners_data_type {
+ int32_t efuse_adjustment;
+ uint32_t programmed_voltage;
+ uint32_t isr_count;
+ uint32_t min_count;
+ uint32_t max_count;
+ struct rbcpr_recmnd_data_type rbcpr_recmnd[RBCPR_NUM_RECMNDS];
+};
+
+struct rbcpr_rail_stats_header_type {
+ uint32_t num_corners;
+ uint32_t num_latest_recommends;
+};
+
+struct rbcpr_rail_stats_footer_type {
+ uint32_t current_corner;
+ uint32_t railway_voltage;
+ uint32_t off_corner;
+ uint32_t margin;
+};
+
+struct rbcpr_stats_type {
+ uint32_t num_rails;
+ uint32_t status;
+};
+
+struct rbcpr_data_type {
+ void __iomem *start;
+ uint32_t len;
+ char buf[RBCPR_BUF_LEN];
+};
+
+static char *rbcpr_rail_labels[] = {
+ [0] = "VDD-CX",
+ [1] = "VDD-GFX",
+};
+
+static char *rbcpr_corner_string[] = {
+ [CORNER_OFF] = "CORNERS_OFF",
+ [CORNER_RETENTION] = "RETENTION",
+ [CORNER_SVS_KRAIT] = "SVS",
+ [CORNER_SVS_SOC] = "SVS_SOC",
+ [CORNER_NOMINAL] = "NOMINAL",
+ [CORNER_TURBO] = "TURBO",
+ [CORNER_SUPER_TURBO] = "SUPER_TURBO",
+};
+
+#define CORNER_STRING(a) \
+ ((a >= CORNER_MAX) ? "INVALID Corner" : rbcpr_corner_string[a])
+
+static struct rbcpr_data_type *rbcpr_data;
+
+static void msm_rpmrbcpr_print_stats_header(
+ struct rbcpr_stats_type *rbcpr_stats, char *buf,
+ uint32_t *pos)
+{
+ *pos += PRINT(buf, *pos, "\n:RBCPR STATS ");
+ *pos += PRINT(buf, *pos, "(%s: %d)", FIELD(rbcpr_stats->num_rails),
+ rbcpr_stats->num_rails);
+ *pos += PRINT(buf, *pos, "(%s: %d)", FIELD(rbcpr_stats->status),
+ rbcpr_stats->status);
+}
+
+static void msm_rpmrbcpr_print_rail_header(
+ struct rbcpr_rail_stats_header_type *rail_header, char *buf,
+ uint32_t *pos)
+{
+ *pos += PRINT(buf, *pos, "(%s: %d)", FIELD(rail_header->num_corners),
+ rail_header->num_corners);
+ *pos += PRINT(buf, *pos, "(%s: %d)",
+ FIELD(rail_header->num_latest_recommends),
+ rail_header->num_latest_recommends);
+}
+
+static void msm_rpmrbcpr_print_corner_recmnds(
+ struct rbcpr_recmnd_data_type *rbcpr_recmnd, char *buf,
+ uint32_t *pos)
+{
+ *pos += PRINT(buf, *pos, "\n\t\t\t :(%s: %d) ",
+ FIELD(rbcpr_recmd->microvolts),
+ rbcpr_recmnd->microvolts);
+ *pos += PRINT(buf, *pos, " (%s: %lld)", FIELD(rbcpr_recmd->timestamp),
+ rbcpr_recmnd->timestamp);
+}
+
+static void msm_rpmrbcpr_print_corner_data(
+ struct rbcpr_corners_data_type *corner, char *buf,
+ uint32_t num_corners, uint32_t *pos)
+{
+ int i;
+
+ *pos += PRINT(buf, *pos, "(%s: %d)",
+ FIELD(corner->efuse_adjustment),
+ corner->efuse_adjustment);
+ *pos += PRINT(buf, *pos, "(%s: %d)",
+ FIELD(corner->programmed_voltage),
+ corner->programmed_voltage);
+ *pos += PRINT(buf, *pos, "(%s: %d)",
+ FIELD(corner->isr_count), corner->isr_count);
+ *pos += PRINT(buf, *pos, "(%s: %d)",
+ FIELD(corner->min_count), corner->min_count);
+ *pos += PRINT(buf, *pos, "(%s: %d)\n",
+ FIELD(corner->max_count), corner->max_count);
+ *pos += PRINT(buf, *pos, "\t\t\t:Latest Recommends");
+ for (i = 0; i < num_corners; i++)
+ msm_rpmrbcpr_print_corner_recmnds(&corner->rbcpr_recmnd[i], buf,
+ pos);
+}
+
+static void msm_rpmrbcpr_print_rail_footer(
+ struct rbcpr_rail_stats_footer_type *rail, char *buf,
+ uint32_t *pos)
+{
+ *pos += PRINT(buf, *pos, "(%s: %s)", FIELD(rail->current_corner),
+ CORNER_STRING(rail->current_corner));
+ *pos += PRINT(buf, *pos, "(%s: %d)",
+ FIELD(rail->railway_voltage), rail->railway_voltage);
+ *pos += PRINT(buf, *pos, "(%s: %d)",
+ FIELD(rail->off_corner), rail->off_corner);
+ *pos += PRINT(buf, *pos, "(%s: %d)\n",
+ FIELD(rail->margin), rail->margin);
+}
+
+static uint32_t msm_rpmrbcpr_read_rpm_data(void)
+{
+ uint32_t read_offset = 0;
+ static struct rbcpr_stats_type rbcpr_stats_header;
+ uint32_t buffer_offset = 0;
+ char *buf = rbcpr_data->buf;
+ int i, j;
+
+ memcpy_fromio(&rbcpr_stats_header, rbcpr_data->start,
+ sizeof(rbcpr_stats_header));
+ read_offset += sizeof(rbcpr_stats_header);
+ msm_rpmrbcpr_print_stats_header(&rbcpr_stats_header, buf,
+ &buffer_offset);
+
+ for (i = 0; i < rbcpr_stats_header.num_rails; i++) {
+ static struct rbcpr_rail_stats_header_type rail_header;
+ static struct rbcpr_rail_stats_footer_type rail_footer;
+
+ memcpy_fromio(&rail_header, (rbcpr_data->start + read_offset),
+ sizeof(rail_header));
+ read_offset += sizeof(rail_header);
+ buffer_offset += PRINT(buf, buffer_offset, "\n:%s Rail Data ",
+ rbcpr_rail_labels[i]);
+ msm_rpmrbcpr_print_rail_header(&rail_header, buf,
+ &buffer_offset);
+
+ for (j = 0; j < rail_header.num_corners; j++) {
+ static struct rbcpr_corners_data_type corner;
+ uint32_t corner_index;
+
+ memcpy_fromio(&corner,
+ (rbcpr_data->start + read_offset),
+ sizeof(corner));
+ read_offset += sizeof(corner);
+
+ /*
+ * RPM doesn't include corner type in the data for the
+ * corner. For now add this hack to know which corners
+ * are used based on number of corners for the rail.
+ */
+ corner_index = j + 3;
+ if (rail_header.num_corners == 3 && j == 2)
+ corner_index++;
+
+ buffer_offset += PRINT(buf, buffer_offset,
+ "\n\t\t:Corner Data: %s ",
+ CORNER_STRING(corner_index));
+ msm_rpmrbcpr_print_corner_data(&corner, buf,
+ rail_header.num_latest_recommends,
+ &buffer_offset);
+ }
+ buffer_offset += PRINT(buf, buffer_offset,
+ "\n\t\t");
+ memcpy_fromio(&rail_footer, (rbcpr_data->start + read_offset),
+ sizeof(rail_footer));
+ read_offset += sizeof(rail_footer);
+ msm_rpmrbcpr_print_rail_footer(&rail_footer, buf,
+ &buffer_offset);
+ }
+ return buffer_offset;
+}
+
+static int msm_rpmrbcpr_file_read(struct seq_file *m, void *data)
+{
+ struct rbcpr_data_type *pdata = m->private;
+ int ret = 0;
+ int curr_status_counter;
+ static int prev_status_counter;
+ static DEFINE_MUTEX(rbcpr_lock);
+
+ mutex_lock(&rbcpr_lock);
+ if (!pdata) {
+ pr_err("%s pdata is null", __func__);
+ ret = -EINVAL;
+ goto exit_rpmrbcpr_file_read;
+ }
+
+ /* Read RPM stats */
+ curr_status_counter = readl_relaxed(pdata->start +
+ offsetof(struct rbcpr_stats_type, status));
+ if (curr_status_counter != prev_status_counter) {
+ pdata->len = msm_rpmrbcpr_read_rpm_data();
+ pdata->len = 0;
+ prev_status_counter = curr_status_counter;
+ }
+
+ seq_printf(m, "%s", pdata->buf);
+
+exit_rpmrbcpr_file_read:
+ mutex_unlock(&rbcpr_lock);
+ return ret;
+}
+
+static int msm_rpmrbcpr_file_open(struct inode *inode, struct file *file)
+{
+ if (!rbcpr_data->start)
+ return -ENODEV;
+ return single_open(file, msm_rpmrbcpr_file_read, inode->i_private);
+}
+
+static const struct file_operations msm_rpmrbcpr_fops = {
+ .open = msm_rpmrbcpr_file_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int msm_rpmrbcpr_validate(struct platform_device *pdev)
+{
+ int ret = 0;
+ uint32_t num_rails;
+
+ num_rails = readl_relaxed(rbcpr_data->start);
+
+ if (num_rails > RBCPR_MAX_RAILS) {
+ pr_err("%s: Invalid number of RPM RBCPR rails %d",
+ __func__, num_rails);
+ ret = -EFAULT;
+ }
+
+ return ret;
+}
+
+static int msm_rpmrbcpr_probe(struct platform_device *pdev)
+{
+ struct dentry *dent;
+ int ret = 0;
+ struct resource *res = NULL;
+ void __iomem *start_ptr = NULL;
+ uint32_t rbcpr_start_addr = 0;
+ char *key = NULL;
+ uint32_t start_addr;
+
+ rbcpr_data = devm_kzalloc(&pdev->dev,
+ sizeof(struct rbcpr_data_type), GFP_KERNEL);
+
+ if (!rbcpr_data)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res) {
+ pr_err("%s: Failed to get IO resource from platform device",
+ __func__);
+ ret = -ENXIO;
+ goto rbcpr_probe_fail;
+ }
+
+ key = "qcom,start-offset";
+ ret = of_property_read_u32(pdev->dev.of_node, key, &start_addr);
+
+ if (ret) {
+ pr_err("%s: Failed to get start offset", __func__);
+ goto rbcpr_probe_fail;
+ }
+
+ start_addr += res->start;
+ start_ptr = ioremap_nocache(start_addr, 4);
+
+ if (!start_ptr) {
+ pr_err("%s: Failed to remap RBCPR start pointer",
+ __func__);
+ goto rbcpr_probe_fail;
+ }
+
+ rbcpr_start_addr = res->start + readl_relaxed(start_ptr);
+ res->end = rbcpr_start_addr + RBCPR_STATS_MAX_SIZE;
+
+ if ((rbcpr_start_addr > (res->end - RBCPR_STATS_MAX_SIZE)) ||
+ (rbcpr_start_addr < start_addr)) {
+ pr_err("%s: Invalid start address for rbcpr stats 0x%x",
+ __func__, rbcpr_start_addr);
+ goto rbcpr_probe_fail;
+ }
+
+ rbcpr_data->start = devm_ioremap_nocache(&pdev->dev, rbcpr_start_addr,
+ RBCPR_STATS_MAX_SIZE);
+
+ if (!rbcpr_data->start) {
+ pr_err("%s: Failed to remap RBCPR start address",
+ __func__);
+ goto rbcpr_probe_fail;
+ }
+
+ ret = msm_rpmrbcpr_validate(pdev);
+
+ if (ret)
+ goto rbcpr_probe_fail;
+
+ dent = debugfs_create_file("rpm_rbcpr", S_IRUGO, NULL,
+ rbcpr_data, &msm_rpmrbcpr_fops);
+
+ if (!dent) {
+ pr_err("%s: error debugfs_create_file failed\n", __func__);
+ ret = -ENOMEM;
+ goto rbcpr_probe_fail;
+ }
+
+ platform_set_drvdata(pdev, dent);
+rbcpr_probe_fail:
+ iounmap(start_ptr);
+ return ret;
+}
+
+static int msm_rpmrbcpr_remove(struct platform_device *pdev)
+{
+ struct dentry *dent;
+
+ dent = platform_get_drvdata(pdev);
+ debugfs_remove(dent);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+static const struct of_device_id rpmrbcpr_stats_table[] = {
+ {.compatible = "qcom,rpmrbcpr-stats"},
+ {},
+};
+
+static struct platform_driver msm_rpmrbcpr_driver = {
+ .probe = msm_rpmrbcpr_probe,
+ .remove = msm_rpmrbcpr_remove,
+ .driver = {
+ .name = "msm_rpmrbcpr_stats",
+ .owner = THIS_MODULE,
+ .of_match_table = rpmrbcpr_stats_table,
+ },
+};
+
+static int __init msm_rpmrbcpr_init(void)
+{
+ return platform_driver_register(&msm_rpmrbcpr_driver);
+}
+
+static void __exit msm_rpmrbcpr_exit(void)
+{
+ platform_driver_unregister(&msm_rpmrbcpr_driver);
+}
+
+module_init(msm_rpmrbcpr_init);
+module_exit(msm_rpmrbcpr_exit);
diff --git a/drivers/soc/qcom/rpm_stats.c b/drivers/soc/qcom/rpm_stats.c
new file mode 100644
index 000000000000..dacca0efe231
--- /dev/null
+++ b/drivers/soc/qcom/rpm_stats.c
@@ -0,0 +1,570 @@
+/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/uaccess.h>
+#include <asm/arch_timer.h>
+#include "rpm_stats.h"
+
+#define GET_PDATA_OF_ATTR(attr) \
+ (container_of(attr, struct msm_rpmstats_kobj_attr, ka)->pd)
+
+enum {
+ ID_COUNTER,
+ ID_ACCUM_TIME_SCLK,
+ ID_MAX,
+};
+
+static char *msm_rpmstats_id_labels[ID_MAX] = {
+ [ID_COUNTER] = "Count",
+ [ID_ACCUM_TIME_SCLK] = "Total time(uSec)",
+};
+
+#define SCLK_HZ 32768
+#define MSM_ARCH_TIMER_FREQ 19200000
+
+struct msm_rpmstats_record {
+ char name[32];
+ uint32_t id;
+ uint32_t val;
+};
+
+struct msm_rpmstats_private_data {
+ void __iomem *reg_base;
+ u32 num_records;
+ u32 read_idx;
+ u32 len;
+ char buf[320];
+ struct msm_rpmstats_platform_data *platform_data;
+};
+
+struct msm_rpm_stats_data_v2 {
+ u32 stat_type;
+ u32 count;
+ u64 last_entered_at;
+ u64 last_exited_at;
+ u64 accumulated;
+ u32 client_votes;
+ u32 reserved[3];
+};
+
+struct msm_rpmstats_kobj_attr {
+ struct kobj_attribute ka;
+ struct msm_rpmstats_platform_data *pd;
+};
+
+static struct dentry *heap_dent;
+
+static inline u64 get_time_in_sec(u64 counter)
+{
+ do_div(counter, MSM_ARCH_TIMER_FREQ);
+ return counter;
+}
+
+static inline u64 get_time_in_msec(u64 counter)
+{
+ do_div(counter, MSM_ARCH_TIMER_FREQ);
+ counter *= MSEC_PER_SEC;
+ return counter;
+}
+
+static inline int msm_rpmstats_append_data_to_buf(char *buf,
+ struct msm_rpm_stats_data_v2 *data, int buflength)
+{
+ char stat_type[5];
+ u64 time_in_last_mode;
+ u64 time_since_last_mode;
+ u64 actual_last_sleep;
+
+ stat_type[4] = 0;
+ memcpy(stat_type, &data->stat_type, sizeof(u32));
+
+ time_in_last_mode = data->last_exited_at - data->last_entered_at;
+ time_in_last_mode = get_time_in_msec(time_in_last_mode);
+ time_since_last_mode = arch_counter_get_cntvct() - data->last_exited_at;
+ time_since_last_mode = get_time_in_sec(time_since_last_mode);
+ actual_last_sleep = get_time_in_msec(data->accumulated);
+
+ return snprintf(buf, buflength,
+ "RPM Mode:%s\n\t count:%d\ntime in last mode(msec):%llu\n"
+ "time since last mode(sec):%llu\nactual last sleep(msec):%llu\n"
+ "client votes: %#010x\n\n",
+ stat_type, data->count, time_in_last_mode,
+ time_since_last_mode, actual_last_sleep,
+ data->client_votes);
+}
+
+static inline u32 msm_rpmstats_read_long_register_v2(void __iomem *regbase,
+ int index, int offset)
+{
+ return readl_relaxed(regbase + offset +
+ index * sizeof(struct msm_rpm_stats_data_v2));
+}
+
+static inline u64 msm_rpmstats_read_quad_register_v2(void __iomem *regbase,
+ int index, int offset)
+{
+ u64 dst;
+
+ memcpy_fromio(&dst,
+ regbase + offset + index * sizeof(struct msm_rpm_stats_data_v2),
+ 8);
+ return dst;
+}
+
+static inline int msm_rpmstats_copy_stats_v2(
+ struct msm_rpmstats_private_data *prvdata)
+{
+ void __iomem *reg;
+ struct msm_rpm_stats_data_v2 data;
+ int i, length;
+
+ reg = prvdata->reg_base;
+
+ for (i = 0, length = 0; i < prvdata->num_records; i++) {
+
+ data.stat_type = msm_rpmstats_read_long_register_v2(reg, i,
+ offsetof(struct msm_rpm_stats_data_v2,
+ stat_type));
+ data.count = msm_rpmstats_read_long_register_v2(reg, i,
+ offsetof(struct msm_rpm_stats_data_v2, count));
+ data.last_entered_at = msm_rpmstats_read_quad_register_v2(reg,
+ i, offsetof(struct msm_rpm_stats_data_v2,
+ last_entered_at));
+ data.last_exited_at = msm_rpmstats_read_quad_register_v2(reg,
+ i, offsetof(struct msm_rpm_stats_data_v2,
+ last_exited_at));
+
+ data.accumulated = msm_rpmstats_read_quad_register_v2(reg,
+ i, offsetof(struct msm_rpm_stats_data_v2,
+ accumulated));
+ data.client_votes = msm_rpmstats_read_long_register_v2(reg,
+ i, offsetof(struct msm_rpm_stats_data_v2,
+ client_votes));
+ length += msm_rpmstats_append_data_to_buf(prvdata->buf + length,
+ &data, sizeof(prvdata->buf) - length);
+ prvdata->read_idx++;
+ }
+ return length;
+}
+
+static inline unsigned long msm_rpmstats_read_register(void __iomem *regbase,
+ int index, int offset)
+{
+ return readl_relaxed(regbase + index * 12 + (offset + 1) * 4);
+}
+static void msm_rpmstats_strcpy(char *dest, char *src)
+{
+ union {
+ char ch[4];
+ unsigned long word;
+ } string;
+ int index = 0;
+
+ do {
+ int i;
+
+ string.word = readl_relaxed(src + 4 * index);
+ for (i = 0; i < 4; i++) {
+ *dest++ = string.ch[i];
+ if (!string.ch[i])
+ break;
+ }
+ index++;
+ } while (*(dest-1));
+
+}
+static int msm_rpmstats_copy_stats(struct msm_rpmstats_private_data *pdata)
+{
+
+ struct msm_rpmstats_record record;
+ unsigned long ptr;
+ unsigned long offset;
+ char *str;
+ uint64_t usec;
+
+ ptr = msm_rpmstats_read_register(pdata->reg_base, pdata->read_idx, 0);
+ offset = (ptr - (unsigned long)pdata->platform_data->phys_addr_base);
+
+ if (offset > pdata->platform_data->phys_size)
+ str = (char *)ioremap(ptr, SZ_256);
+ else
+ str = (char *) pdata->reg_base + offset;
+
+ msm_rpmstats_strcpy(record.name, str);
+
+ if (offset > pdata->platform_data->phys_size)
+ iounmap(str);
+
+ record.id = msm_rpmstats_read_register(pdata->reg_base,
+ pdata->read_idx, 1);
+ record.val = msm_rpmstats_read_register(pdata->reg_base,
+ pdata->read_idx, 2);
+
+ if (record.id == ID_ACCUM_TIME_SCLK) {
+ usec = record.val * USEC_PER_SEC;
+ do_div(usec, SCLK_HZ);
+ } else
+ usec = (unsigned long)record.val;
+
+ pdata->read_idx++;
+
+ return snprintf(pdata->buf, sizeof(pdata->buf),
+ "RPM Mode:%s\n\t%s:%llu\n",
+ record.name,
+ msm_rpmstats_id_labels[record.id],
+ usec);
+}
+
+static ssize_t msm_rpmstats_file_read(struct file *file, char __user *bufu,
+ size_t count, loff_t *ppos)
+{
+ struct msm_rpmstats_private_data *prvdata;
+
+ prvdata = file->private_data;
+ if (!prvdata)
+ return -EINVAL;
+
+ if (!bufu || count == 0)
+ return -EINVAL;
+
+ if (prvdata->platform_data->version == 1) {
+ if (!prvdata->num_records)
+ prvdata->num_records = readl_relaxed(prvdata->reg_base);
+ }
+
+ if ((*ppos >= prvdata->len) &&
+ (prvdata->read_idx < prvdata->num_records)) {
+ if (prvdata->platform_data->version == 1)
+ prvdata->len = msm_rpmstats_copy_stats(prvdata);
+ else if (prvdata->platform_data->version == 2)
+ prvdata->len = msm_rpmstats_copy_stats_v2(prvdata);
+ *ppos = 0;
+ }
+ return simple_read_from_buffer(bufu, count, ppos,
+ prvdata->buf, prvdata->len);
+}
+
+static int msm_rpmstats_file_open(struct inode *inode, struct file *file)
+{
+ struct msm_rpmstats_private_data *prvdata;
+ struct msm_rpmstats_platform_data *pdata;
+
+ pdata = inode->i_private;
+
+ file->private_data =
+ kmalloc(sizeof(struct msm_rpmstats_private_data), GFP_KERNEL);
+
+ if (!file->private_data)
+ return -ENOMEM;
+ prvdata = file->private_data;
+
+ prvdata->reg_base = ioremap_nocache(pdata->phys_addr_base,
+ pdata->phys_size);
+ if (!prvdata->reg_base) {
+ kfree(file->private_data);
+ prvdata = NULL;
+ pr_err("%s: ERROR could not ioremap start=%pa, len=%u\n",
+ __func__, &pdata->phys_addr_base,
+ pdata->phys_size);
+ return -EBUSY;
+ }
+
+ prvdata->read_idx = prvdata->num_records = prvdata->len = 0;
+ prvdata->platform_data = pdata;
+ if (pdata->version == 2)
+ prvdata->num_records = 2;
+
+ return 0;
+}
+
+static int msm_rpmstats_file_close(struct inode *inode, struct file *file)
+{
+ struct msm_rpmstats_private_data *private = file->private_data;
+
+ if (private->reg_base)
+ iounmap(private->reg_base);
+ kfree(file->private_data);
+
+ return 0;
+}
+
+static const struct file_operations msm_rpmstats_fops = {
+ .owner = THIS_MODULE,
+ .open = msm_rpmstats_file_open,
+ .read = msm_rpmstats_file_read,
+ .release = msm_rpmstats_file_close,
+ .llseek = no_llseek,
+};
+
+static int msm_rpmheap_file_show(struct seq_file *m, void *v)
+{
+ struct msm_rpmstats_platform_data *pdata;
+ void __iomem *reg_base;
+ uint32_t rpmheap_free;
+
+ if (!m->private)
+ return -EINVAL;
+
+ pdata = m->private;
+
+ reg_base = ioremap_nocache(pdata->heap_phys_addrbase, SZ_4);
+ if (!reg_base) {
+ pr_err("%s: ERROR could not ioremap start=%p\n",
+ __func__, &pdata->heap_phys_addrbase);
+ return -EBUSY;
+ }
+
+ rpmheap_free = readl_relaxed(reg_base);
+ iounmap(reg_base);
+
+ seq_printf(m, "RPM FREE HEAP SPACE is 0x%x Bytes\n", rpmheap_free);
+ return 0;
+}
+
+static int msm_rpmheap_file_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, msm_rpmheap_file_show, inode->i_private);
+}
+
+static const struct file_operations msm_rpmheap_fops = {
+ .owner = THIS_MODULE,
+ .open = msm_rpmheap_file_open,
+ .read = seq_read,
+ .release = single_release,
+ .llseek = no_llseek,
+};
+
+static ssize_t rpmstats_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct msm_rpmstats_private_data *prvdata = NULL;
+ struct msm_rpmstats_platform_data *pdata = NULL;
+
+ pdata = GET_PDATA_OF_ATTR(attr);
+
+ prvdata =
+ kmalloc(sizeof(*prvdata), GFP_KERNEL);
+ if (!prvdata)
+ return -ENOMEM;
+
+ prvdata->reg_base = ioremap_nocache(pdata->phys_addr_base,
+ pdata->phys_size);
+ if (!prvdata->reg_base) {
+ kfree(prvdata);
+ pr_err("%s: ERROR could not ioremap start=%pa, len=%u\n",
+ __func__, &pdata->phys_addr_base,
+ pdata->phys_size);
+ return -EBUSY;
+ }
+
+ prvdata->read_idx = prvdata->num_records = prvdata->len = 0;
+ prvdata->platform_data = pdata;
+ if (pdata->version == 2)
+ prvdata->num_records = 2;
+
+ if (prvdata->platform_data->version == 1) {
+ if (!prvdata->num_records)
+ prvdata->num_records =
+ readl_relaxed(prvdata->reg_base);
+ }
+
+ if (prvdata->read_idx < prvdata->num_records) {
+ if (prvdata->platform_data->version == 1)
+ prvdata->len = msm_rpmstats_copy_stats(prvdata);
+ else if (prvdata->platform_data->version == 2)
+ prvdata->len = msm_rpmstats_copy_stats_v2(
+ prvdata);
+ }
+
+ return snprintf(buf, prvdata->len, prvdata->buf);
+}
+
+static int msm_rpmstats_create_sysfs(struct msm_rpmstats_platform_data *pd)
+{
+ struct kobject *module_kobj = NULL;
+ struct kobject *rpmstats_kobj = NULL;
+ struct msm_rpmstats_kobj_attr *rpms_ka = NULL;
+ int ret = 0;
+
+ module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+ if (!module_kobj) {
+ pr_err("%s: Cannot find module_kset\n", __func__);
+ return -ENODEV;
+ }
+
+ rpmstats_kobj = kobject_create_and_add("rpmstats", module_kobj);
+ if (!rpmstats_kobj) {
+ pr_err("%s: Cannot create rpmstats kobject\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ rpms_ka = kzalloc(sizeof(*rpms_ka), GFP_KERNEL);
+ if (!rpms_ka) {
+ kobject_put(rpmstats_kobj);
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ sysfs_attr_init(&rpms_ka->ka.attr);
+ rpms_ka->pd = pd;
+ rpms_ka->ka.attr.mode = 0444;
+ rpms_ka->ka.attr.name = "stats";
+ rpms_ka->ka.show = rpmstats_show;
+ rpms_ka->ka.store = NULL;
+
+ ret = sysfs_create_file(rpmstats_kobj, &rpms_ka->ka.attr);
+
+fail:
+ return ret;
+}
+
+static int msm_rpmstats_probe(struct platform_device *pdev)
+{
+ struct dentry *dent = NULL;
+ struct msm_rpmstats_platform_data *pdata;
+ struct msm_rpmstats_platform_data *pd;
+ struct resource *res = NULL, *offset = NULL;
+ struct device_node *node = NULL;
+ uint32_t offset_addr = 0;
+ void __iomem *phys_ptr = NULL;
+ int ret = 0;
+
+ if (!pdev)
+ return -EINVAL;
+
+ pdata = kzalloc(sizeof(struct msm_rpmstats_platform_data), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "phys_addr_base");
+ if (!res)
+ return -EINVAL;
+
+ offset = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "offset_addr");
+ if (offset) {
+ /* Remap the rpm-stats pointer */
+ phys_ptr = ioremap_nocache(offset->start, SZ_4);
+ if (!phys_ptr) {
+ pr_err("%s: Failed to ioremap address: %x\n",
+ __func__, offset_addr);
+ return -ENODEV;
+ }
+ offset_addr = readl_relaxed(phys_ptr);
+ iounmap(phys_ptr);
+ }
+
+ pdata->phys_addr_base = res->start + offset_addr;
+
+ pdata->phys_size = resource_size(res);
+ node = pdev->dev.of_node;
+ if (pdev->dev.platform_data) {
+ pd = pdev->dev.platform_data;
+ pdata->version = pd->version;
+
+ } else if (node)
+ ret = of_property_read_u32(node,
+ "qcom,sleep-stats-version", &pdata->version);
+
+ if (!ret) {
+
+ dent = debugfs_create_file("rpm_stats", S_IRUGO, NULL,
+ pdata, &msm_rpmstats_fops);
+
+ if (!dent) {
+ pr_err("%s: ERROR rpm_stats debugfs_create_file fail\n",
+ __func__);
+ kfree(pdata);
+ return -ENOMEM;
+ }
+
+ } else {
+ kfree(pdata);
+ return -EINVAL;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "heap_phys_addrbase");
+ if (res) {
+ heap_dent = debugfs_create_file("rpm_heap", S_IRUGO, NULL,
+ pdata, &msm_rpmheap_fops);
+
+ if (!heap_dent) {
+ pr_err("%s: ERROR rpm_heap debugfs_create_file fail\n",
+ __func__);
+ kfree(pdata);
+ return -ENOMEM;
+ }
+ pdata->heap_phys_addrbase = res->start;
+ }
+
+ msm_rpmstats_create_sysfs(pdata);
+
+ platform_set_drvdata(pdev, dent);
+ return 0;
+}
+
+static int msm_rpmstats_remove(struct platform_device *pdev)
+{
+ struct dentry *dent;
+
+ dent = platform_get_drvdata(pdev);
+ debugfs_remove(dent);
+ debugfs_remove(heap_dent);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+static const struct of_device_id rpm_stats_table[] = {
+ {.compatible = "qcom,rpm-stats"},
+ {},
+};
+
+static struct platform_driver msm_rpmstats_driver = {
+ .probe = msm_rpmstats_probe,
+ .remove = msm_rpmstats_remove,
+ .driver = {
+ .name = "msm_rpm_stat",
+ .owner = THIS_MODULE,
+ .of_match_table = rpm_stats_table,
+ },
+};
+static int __init msm_rpmstats_init(void)
+{
+ return platform_driver_register(&msm_rpmstats_driver);
+}
+static void __exit msm_rpmstats_exit(void)
+{
+ platform_driver_unregister(&msm_rpmstats_driver);
+}
+module_init(msm_rpmstats_init);
+module_exit(msm_rpmstats_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM RPM Statistics driver");
+MODULE_ALIAS("platform:msm_stat_log");
diff --git a/drivers/soc/qcom/rpm_stats.h b/drivers/soc/qcom/rpm_stats.h
new file mode 100644
index 000000000000..7b61cd4da1f8
--- /dev/null
+++ b/drivers/soc/qcom/rpm_stats.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_RPM_STATS_H
+#define __ARCH_ARM_MACH_MSM_RPM_STATS_H
+
+#include <linux/types.h>
+
+struct msm_rpmstats_platform_data {
+ phys_addr_t phys_addr_base;
+ phys_addr_t heap_phys_addrbase;
+ u32 phys_size;
+ u32 version;
+};
+
+struct msm_rpm_master_stats_platform_data {
+ phys_addr_t phys_addr_base;
+ u32 phys_size;
+ char **masters;
+ /*
+ * RPM maintains PC stats for each master in MSG RAM,
+ * it allocates 256 bytes for this use.
+ * No of masters differs for different targets.
+ * Based on the number of masters, linux rpm stat
+ * driver reads (32 * num_masters) bytes to display
+ * master stats.
+ */
+ s32 num_masters;
+ u32 master_offset;
+ u32 version;
+};
+#endif
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 6e11f9ca5ce2..2d480f1af11f 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -649,15 +649,14 @@ static int qpnpint_get_irqchip_state(struct irq_data *d,
}
static struct irq_chip pmic_arb_irqchip = {
- .name = "pmic_arb",
- .irq_ack = qpnpint_irq_ack,
- .irq_eoi = qpnpint_irq_ack,
- .irq_mask = qpnpint_irq_mask,
- .irq_unmask = qpnpint_irq_unmask,
- .irq_set_type = qpnpint_irq_set_type,
+ .name = "pmic_arb",
+ .irq_ack = qpnpint_irq_ack,
+ .irq_mask = qpnpint_irq_mask,
+ .irq_unmask = qpnpint_irq_unmask,
+ .irq_set_type = qpnpint_irq_set_type,
.irq_get_irqchip_state = qpnpint_get_irqchip_state,
- .flags = IRQCHIP_MASK_ON_SUSPEND
- | IRQCHIP_SKIP_SET_WAKE,
+ .flags = IRQCHIP_MASK_ON_SUSPEND
+ | IRQCHIP_SKIP_SET_WAKE,
};
static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
@@ -716,7 +715,7 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
dev_dbg(&pa->spmic->dev, "virq = %u, hwirq = %lu\n", virq, hwirq);
- irq_set_chip_and_handler(virq, &pmic_arb_irqchip, handle_fasteoi_irq);
+ irq_set_chip_and_handler(virq, &pmic_arb_irqchip, handle_level_irq);
irq_set_chip_data(virq, d->host_data);
irq_set_noprobe(virq);
return 0;
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 743a2a5922dc..f2a21697d431 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -166,12 +166,12 @@ static bool psm_enabled;
static bool psm_nodes_called;
static bool psm_probed;
static bool freq_mitigation_enabled;
+static bool boot_freq_mitig_enabled;
static bool ocr_enabled;
static bool ocr_nodes_called;
static bool ocr_probed;
static bool ocr_reg_init_defer;
static bool hotplug_enabled;
-static bool interrupt_mode_enable;
static bool msm_thermal_probed;
static bool gfx_crit_phase_ctrl_enabled;
static bool gfx_warm_phase_ctrl_enabled;
@@ -3521,6 +3521,8 @@ static void do_freq_control(int temp)
uint32_t cpu = 0;
uint32_t max_freq = cpus[cpu].limited_max_freq;
+ if (!boot_freq_mitig_enabled)
+ return;
if (core_ptr)
return do_cluster_freq_ctrl(temp);
if (!freq_table_get)
@@ -4858,10 +4860,9 @@ static void __ref disable_msm_thermal(void)
static void interrupt_mode_init(void)
{
- if (!msm_thermal_probed) {
- interrupt_mode_enable = true;
+ if (!msm_thermal_probed)
return;
- }
+
if (polling_enabled) {
polling_enabled = 0;
create_sensor_zone_id_map();
@@ -5151,7 +5152,7 @@ static void msm_thermal_panic_notifier_init(struct device *dev)
&msm_thermal_panic_notifier);
}
-int msm_thermal_pre_init(struct device *dev)
+static int msm_thermal_pre_init(struct device *dev)
{
int ret = 0;
@@ -5298,6 +5299,7 @@ int msm_thermal_init(struct msm_thermal_data *pdata)
{
int ret = 0;
+ msm_thermal_ioctl_init();
ret = devmgr_devices_init(pdata->pdev);
if (ret)
pr_err("cannot initialize devm devices. err:%d\n", ret);
@@ -5319,16 +5321,19 @@ int msm_thermal_init(struct msm_thermal_data *pdata)
if (ret)
pr_err("cannot register cpufreq notifier. err:%d\n", ret);
- register_reboot_notifier(&msm_thermal_reboot_notifier);
- pm_notifier(msm_thermal_suspend_callback, 0);
+ if (!lmh_dcvs_available) {
+ register_reboot_notifier(&msm_thermal_reboot_notifier);
+ pm_notifier(msm_thermal_suspend_callback, 0);
+ }
INIT_DELAYED_WORK(&retry_hotplug_work, retry_hotplug);
- INIT_DELAYED_WORK(&check_temp_work, check_temp);
- schedule_delayed_work(&check_temp_work, 0);
if (num_possible_cpus() > 1) {
cpus_previously_online_update();
register_cpu_notifier(&msm_thermal_cpu_notifier);
}
+
+ INIT_DELAYED_WORK(&check_temp_work, check_temp);
+ schedule_delayed_work(&check_temp_work, 0);
msm_thermal_panic_notifier_init(&pdata->pdev->dev);
return ret;
@@ -5378,15 +5383,6 @@ static int vdd_restriction_reg_init(struct platform_device *pdev)
for (i = 0; i < rails_cnt; i++) {
if (rails[i].freq_req == 1) {
usefreq |= BIT(i);
- check_freq_table();
- /*
- * Restrict frequency by default until we have made
- * our first temp reading
- */
- if (freq_table_get)
- ret = vdd_restriction_apply_freq(&rails[i], 0);
- else
- pr_info("Defer vdd rstr freq init.\n");
} else {
rails[i].reg = devm_regulator_get(&pdev->dev,
rails[i].name);
@@ -5404,11 +5400,6 @@ static int vdd_restriction_reg_init(struct platform_device *pdev)
rails[i].name);
return ret;
}
- /*
- * Restrict votlage by default until we have made
- * our first temp reading
- */
- ret = vdd_restriction_apply_voltage(&rails[i], 0);
}
}
@@ -6215,6 +6206,18 @@ static int fetch_cpu_mitigaiton_info(struct msm_thermal_data *data,
int _cpu = 0, err = 0;
struct device_node *cpu_node = NULL, *limits = NULL, *tsens = NULL;
+ char *key = NULL;
+ struct device_node *node = pdev->dev.of_node;
+
+ key = "qcom,sensor-id";
+ err = of_property_read_u32(node, key, &data->sensor_id);
+ if (err)
+ goto fetch_mitig_exit;
+
+ key = "qcom,poll-ms";
+ err = of_property_read_u32(node, key, &data->poll_ms);
+ if (err)
+ goto fetch_mitig_exit;
for_each_possible_cpu(_cpu) {
const char *sensor_name = NULL;
@@ -6556,6 +6559,12 @@ static int probe_cc(struct device_node *node, struct msm_thermal_data *data,
hotplug_enabled = 1;
}
+ key = "qcom,online-hotplug-core";
+ if (of_property_read_bool(node, key))
+ online_core = true;
+ else
+ online_core = false;
+
key = "qcom,core-limit-temp";
ret = of_property_read_u32(node, key, &data->core_limit_temp_degC);
if (ret)
@@ -6824,6 +6833,22 @@ static int probe_freq_mitigation(struct device_node *node,
char *key = NULL;
int ret = 0;
+ key = "qcom,limit-temp";
+ ret = of_property_read_u32(node, key, &data->limit_temp_degC);
+ if (ret)
+ goto PROBE_FREQ_EXIT;
+
+ key = "qcom,temp-hysteresis";
+ ret = of_property_read_u32(node, key, &data->temp_hysteresis_degC);
+ if (ret)
+ goto PROBE_FREQ_EXIT;
+
+ key = "qcom,freq-step";
+ ret = of_property_read_u32(node, key, &data->bootup_freq_step);
+ if (ret)
+ goto PROBE_FREQ_EXIT;
+ boot_freq_mitig_enabled = true;
+
key = "qcom,freq-mitigation-temp";
ret = of_property_read_u32(node, key, &data->freq_mitig_temp_degc);
if (ret)
@@ -7156,92 +7181,8 @@ static int thermal_config_debugfs_read(struct seq_file *m, void *data)
return 0;
}
-static int msm_thermal_dev_probe(struct platform_device *pdev)
+static void msm_thermal_late_sysfs_init(void)
{
- int ret = 0;
- char *key = NULL;
- struct device_node *node = pdev->dev.of_node;
- struct msm_thermal_data data;
-
- if (!mitigation)
- return ret;
-
- memset(&data, 0, sizeof(struct msm_thermal_data));
- data.pdev = pdev;
-
- ret = msm_thermal_pre_init(&pdev->dev);
- if (ret) {
- pr_err("thermal pre init failed. err:%d\n", ret);
- goto fail;
- }
-
- key = "qcom,sensor-id";
- ret = of_property_read_u32(node, key, &data.sensor_id);
- if (ret)
- goto fail;
-
- key = "qcom,poll-ms";
- ret = of_property_read_u32(node, key, &data.poll_ms);
- if (ret)
- goto fail;
-
- key = "qcom,limit-temp";
- ret = of_property_read_u32(node, key, &data.limit_temp_degC);
- if (ret)
- goto fail;
-
- key = "qcom,temp-hysteresis";
- ret = of_property_read_u32(node, key, &data.temp_hysteresis_degC);
- if (ret)
- goto fail;
-
- key = "qcom,freq-step";
- ret = of_property_read_u32(node, key, &data.bootup_freq_step);
- if (ret)
- goto fail;
-
- key = "qcom,online-hotplug-core";
- if (of_property_read_bool(node, key))
- online_core = true;
- else
- online_core = false;
-
- probe_sensor_info(node, &data, pdev);
- ret = probe_cc(node, &data, pdev);
-
- ret = probe_freq_mitigation(node, &data, pdev);
- ret = probe_cx_phase_ctrl(node, &data, pdev);
- ret = probe_gfx_phase_ctrl(node, &data, pdev);
- ret = probe_therm_reset(node, &data, pdev);
-
- ret = probe_vdd_mx(node, &data, pdev);
- if (ret == -EPROBE_DEFER)
- goto fail;
- /*
- * Probe optional properties below. Call probe_psm before
- * probe_vdd_rstr because rpm_regulator_get has to be called
- * before devm_regulator_get
- * probe_ocr should be called after probe_vdd_rstr to reuse the
- * regualtor handle. calling devm_regulator_get more than once
- * will fail.
- */
- ret = probe_psm(node, &data, pdev);
- if (ret == -EPROBE_DEFER)
- goto fail;
-
- update_cpu_topology(&pdev->dev);
- ret = probe_vdd_rstr(node, &data, pdev);
- if (ret == -EPROBE_DEFER)
- goto fail;
- ret = probe_ocr(node, &data, pdev);
-
- ret = fetch_cpu_mitigaiton_info(&data, pdev);
- if (ret) {
- pr_err("Error fetching CPU mitigation information. err:%d\n",
- ret);
- goto probe_exit;
- }
-
/*
* In case sysfs add nodes get called before probe function.
* Need to make sure sysfs node is created again
@@ -7266,20 +7207,77 @@ static int msm_thermal_dev_probe(struct platform_device *pdev)
create_cpu_topology_sysfs();
cluster_info_nodes_called = false;
}
- msm_thermal_ioctl_init();
- ret = msm_thermal_init(&data);
- msm_thermal_probed = true;
+}
- if (interrupt_mode_enable) {
- interrupt_mode_init();
- interrupt_mode_enable = false;
+static int probe_deferrable_properties(struct device_node *node,
+ struct msm_thermal_data *data, struct platform_device *pdev)
+{
+ int ret = 0;
+
+ /*
+ * Probe optional properties below. Call probe_psm before
+ * probe_vdd_rstr because rpm_regulator_get has to be called
+ * before devm_regulator_get
+ * probe_ocr should be called after probe_vdd_rstr to reuse the
+ * regualtor handle. calling devm_regulator_get more than once
+ * will fail.
+ */
+ ret = probe_psm(node, data, pdev);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ ret = probe_vdd_rstr(node, data, pdev);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ probe_ocr(node, data, pdev);
+ ret = probe_vdd_mx(node, data, pdev);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ return 0;
+}
+
+static int msm_thermal_dev_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct device_node *node = pdev->dev.of_node;
+ struct msm_thermal_data data;
+
+ if (!mitigation)
+ return ret;
+
+ memset(&data, 0, sizeof(struct msm_thermal_data));
+ data.pdev = pdev;
+
+ ret = msm_thermal_pre_init(&pdev->dev);
+ if (ret) {
+ pr_err("thermal pre init failed. err:%d\n", ret);
+ goto probe_exit;
}
+ ret = probe_deferrable_properties(node, &data, pdev);
+ if (ret)
+ goto probe_exit;
- return ret;
-fail:
+ probe_sensor_info(node, &data, pdev);
+ probe_cc(node, &data, pdev);
+ probe_freq_mitigation(node, &data, pdev);
+ probe_cx_phase_ctrl(node, &data, pdev);
+ probe_gfx_phase_ctrl(node, &data, pdev);
+ probe_therm_reset(node, &data, pdev);
+ update_cpu_topology(&pdev->dev);
+ ret = fetch_cpu_mitigaiton_info(&data, pdev);
+ if (ret) {
+ pr_err("Error fetching CPU mitigation information. err:%d\n",
+ ret);
+ goto probe_exit;
+ }
+ msm_thermal_late_sysfs_init();
+ ret = msm_thermal_init(&data);
if (ret)
- pr_err("Failed reading node=%s, key=%s. err:%d\n",
- node->full_name, key, ret);
+ goto probe_exit;
+ msm_thermal_probed = true;
+
probe_exit:
return ret;
}
@@ -7410,7 +7408,6 @@ int __init msm_thermal_late_init(void)
}
}
msm_thermal_add_mx_nodes();
- interrupt_mode_init();
create_cpu_topology_sysfs();
create_thermal_debugfs();
msm_thermal_add_bucket_info_nodes();
diff --git a/drivers/usb/gadget/function/f_diag.c b/drivers/usb/gadget/function/f_diag.c
index 87939140f82e..bddee84d81e0 100644
--- a/drivers/usb/gadget/function/f_diag.c
+++ b/drivers/usb/gadget/function/f_diag.c
@@ -204,8 +204,9 @@ static void diag_context_release(struct kref *kref)
static void diag_update_pid_and_serial_num(struct diag_context *ctxt)
{
struct usb_composite_dev *cdev = ctxt->cdev;
- struct usb_gadget_strings *table;
+ struct usb_gadget_strings **table;
struct usb_string *s;
+ struct usb_gadget_string_container *uc;
struct dload_struct local_diag_dload = { 0 };
/*
@@ -223,30 +224,26 @@ static void diag_update_pid_and_serial_num(struct diag_context *ctxt)
/* update pid */
local_diag_dload.magic_struct.pid = PID_MAGIC_ID;
local_diag_dload.pid = cdev->desc.idProduct;
+ local_diag_dload.magic_struct.serial_num = SERIAL_NUM_MAGIC_ID;
- /* pass on product id and serial number to dload */
- if (!cdev->desc.iSerialNumber) {
- /*
- * Serial number is filled by the composite driver. So
- * it is fair enough to assume that it will always be
- * found at first table of strings.
- */
- table = *(cdev->driver->strings);
+ list_for_each_entry(uc, &cdev->gstrings, list) {
+ table = (struct usb_gadget_strings **)uc->stash;
if (!table) {
pr_err("%s: can't update dload cookie\n", __func__);
- return;
+ break;
}
- for (s = table->strings; s && s->s; s++) {
+
+ for (s = (*table)->strings; s && s->s; s++) {
if (s->id == cdev->desc.iSerialNumber) {
- local_diag_dload.magic_struct.serial_num =
- SERIAL_NUM_MAGIC_ID;
strlcpy(local_diag_dload.serial_number, s->s,
SERIAL_NUMBER_LENGTH);
- break;
+ goto update_dload;
}
}
+
}
+update_dload:
pr_debug("%s: dload:%p pid:%x serial_num:%s\n",
__func__, diag_dload, local_diag_dload.pid,
local_diag_dload.serial_number);
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 4a7be5416acb..15d85b40388f 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -3704,7 +3704,7 @@ static int mdss_fb_set_par(struct fb_info *info)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
struct fb_var_screeninfo *var = &info->var;
- int old_imgType;
+ int old_imgType, old_format;
int ret = 0;
ret = mdss_fb_pan_idle(mfd);
@@ -3787,6 +3787,12 @@ static int mdss_fb_set_par(struct fb_info *info)
mfd->fbi->fix.smem_len = PAGE_ALIGN(mfd->fbi->fix.line_length *
mfd->fbi->var.yres) * mfd->fb_page;
+ old_format = mdss_grayscale_to_mdp_format(var->grayscale);
+ if (!IS_ERR_VALUE(old_format)) {
+ if (old_format != mfd->panel_info->out_format)
+ mfd->panel_reconfig = true;
+ }
+
if (mfd->panel_reconfig || (mfd->fb_imgType != old_imgType)) {
mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
mdss_fb_var_to_panelinfo(var, mfd->panel_info);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.c b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
index 018d7519bf8f..ab2c9c0e501f 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
@@ -2346,6 +2346,24 @@ bool hdmi_edid_get_scdc_support(void *input)
return scdc_present;
}
+/**
+ * hdmi_edid_sink_scramble_override() - check if override has been enabled
+ * @input: edid data
+ *
+ * Return true if scrambling override is enabled false otherwise.
+ */
+bool hdmi_edid_sink_scramble_override(void *input)
+{
+ struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
+
+ if (edid_ctrl->edid_override &&
+ (edid_ctrl->override_data.scramble != -1))
+ return true;
+
+ return false;
+
+}
+
bool hdmi_edid_get_sink_scrambler_support(void *input)
{
struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.h b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
index 6cf0f1240f8a..4dd92ed32364 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
@@ -32,6 +32,7 @@ int hdmi_edid_parser(void *edid_ctrl);
u32 hdmi_edid_get_raw_data(void *edid_ctrl, u8 *buf, u32 size);
u8 hdmi_edid_get_sink_scaninfo(void *edid_ctrl, u32 resolution);
u32 hdmi_edid_get_sink_mode(void *edid_ctrl);
+bool hdmi_edid_sink_scramble_override(void *input);
bool hdmi_edid_get_sink_scrambler_support(void *input);
bool hdmi_edid_get_scdc_support(void *input);
int hdmi_edid_get_audio_blk(void *edid_ctrl,
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index 94b7bf02ccd0..4f266fffadfb 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -77,6 +77,10 @@
#define HDMI_DEFAULT_MAX_PCLK_RATE 148500
#define HDMI_TX_3_MAX_PCLK_RATE 297000
#define HDMI_TX_4_MAX_PCLK_RATE 600000
+#define HDMI_TX_KHZ_TO_HZ 1000U
+
+#define hdmi_tx_get_fd(x) (x ? hdmi_ctrl->feature_data[ffs(x) - 1] : 0)
+#define hdmi_tx_set_fd(x, y) {if (x) hdmi_ctrl->feature_data[ffs(x) - 1] = y; }
/* Enable HDCP by default */
static bool hdcp_feature_on = true;
@@ -90,6 +94,9 @@ static bool hdcp_feature_on = true;
#define VENDOR_IFRAME_LINE_NUMBER 3
#define MAX_EDID_READ_RETRY 5
+#define HDMI_TX_MIN_FPS 20000
+#define HDMI_TX_MAX_FPS 120000
+
enum {
DATA_BYTE_1,
DATA_BYTE_2,
@@ -162,6 +169,7 @@ static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
static int hdmi_tx_setup_tmds_clk_rate(struct hdmi_tx_ctrl *hdmi_ctrl);
static void hdmi_tx_set_vendor_specific_infoframe(
struct hdmi_tx_ctrl *hdmi_ctrl);
+static void hdmi_tx_fps_work(struct work_struct *work);
static struct mdss_hw hdmi_tx_hw = {
.hw_ndx = MDSS_HW_HDMI,
@@ -390,12 +398,15 @@ static int hdmi_tx_get_vic_from_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl,
new_vic = pinfo->vic;
DEV_DBG("%s: %s is supported\n", __func__,
msm_hdmi_mode_2string(new_vic));
+ pinfo->lcdc.frame_rate = info.refresh_rate;
} else {
DEV_ERR("%s: invalid or not supported vic %d\n",
__func__, pinfo->vic);
return -EPERM;
}
} else {
+ u64 pclk;
+
timing.active_h = pinfo->xres;
timing.back_porch_h = pinfo->lcdc.h_back_porch;
timing.front_porch_h = pinfo->lcdc.h_front_porch;
@@ -416,7 +427,10 @@ static int hdmi_tx_get_vic_from_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl,
timing.active_v, timing.back_porch_v,
timing.front_porch_v, timing.pulse_width_v, v_total);
- timing.pixel_freq = ((unsigned long int)pinfo->clk_rate / 1000);
+ pclk = pinfo->clk_rate;
+ do_div(pclk, HDMI_TX_KHZ_TO_HZ);
+
+ timing.pixel_freq = (unsigned long) pclk;
if (h_total && v_total) {
timing.refresh_rate = ((timing.pixel_freq * 1000) /
(h_total * v_total)) * 1000;
@@ -436,7 +450,7 @@ static int hdmi_tx_get_vic_from_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl,
static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
{
return hdmi_edid_get_sink_mode(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
+ hdmi_tx_get_fd(HDMI_TX_FEAT_EDID)) ? 0 : 1;
} /* hdmi_tx_is_dvi_mode */
static inline bool hdmi_tx_is_panel_on(struct hdmi_tx_ctrl *hdmi_ctrl)
@@ -446,21 +460,22 @@ static inline bool hdmi_tx_is_panel_on(struct hdmi_tx_ctrl *hdmi_ctrl)
static inline bool hdmi_tx_is_cec_wakeup_en(struct hdmi_tx_ctrl *hdmi_ctrl)
{
- if (!hdmi_ctrl || !hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_HW])
+ void *fd = hdmi_tx_get_fd(HDMI_TX_FEAT_CEC_HW);
+
+ if (!hdmi_ctrl || !fd)
return false;
- return hdmi_cec_is_wakeup_en(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_HW]);
+ return hdmi_cec_is_wakeup_en(fd);
}
-static inline void hdmi_tx_cec_device_suspend(struct hdmi_tx_ctrl *hdmi_ctrl,
- bool suspend)
+static inline void hdmi_tx_cec_device_suspend(struct hdmi_tx_ctrl *hdmi_ctrl)
{
- if (!hdmi_ctrl || !hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_HW])
+ void *fd = hdmi_tx_get_fd(HDMI_TX_FEAT_CEC_HW);
+
+ if (!hdmi_ctrl || !fd)
return;
- hdmi_cec_device_suspend(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_HW],
- suspend);
+ hdmi_cec_device_suspend(fd, hdmi_ctrl->panel_suspend);
}
@@ -580,7 +595,7 @@ void *hdmi_get_featuredata_from_sysfs_dev(struct device *device,
hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(device);
if (hdmi_ctrl)
- return hdmi_ctrl->feature_data[feature_type];
+ return hdmi_tx_get_fd(feature_type);
else
return NULL;
@@ -742,6 +757,41 @@ end:
return ret;
}
+static int hdmi_tx_update_pixel_clk(struct hdmi_tx_ctrl *hdmi_ctrl, int fps)
+{
+ struct dss_module_power *power_data = NULL;
+ struct mdss_panel_info *pinfo;
+ int rc = 0;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ rc = -EINVAL;
+ goto end;
+ }
+
+ pinfo = &hdmi_ctrl->panel_data.panel_info;
+
+ power_data = &hdmi_ctrl->pdata.power_data[HDMI_TX_CORE_PM];
+ if (!power_data) {
+ DEV_ERR("%s: Error: invalid power data\n", __func__);
+ rc = -EINVAL;
+ goto end;
+ }
+
+ if (power_data->clk_config->rate == pinfo->clk_rate) {
+ rc = -EINVAL;
+ goto end;
+ }
+
+ power_data->clk_config->rate = pinfo->clk_rate;
+
+ DEV_DBG("%s: rate %ld\n", __func__, power_data->clk_config->rate);
+
+ msm_dss_clk_set_rate(power_data->clk_config, power_data->num_clk);
+end:
+ return rc;
+}
+
static ssize_t hdmi_tx_sysfs_wta_hot_plug(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -935,6 +985,9 @@ static ssize_t hdmi_tx_sysfs_wta_hpd(struct device *dev,
hdmi_tx_config_5v(hdmi_ctrl, false);
} else {
hdmi_tx_hpd_off(hdmi_ctrl);
+
+ hdmi_ctrl->sdev.state = 0;
+ hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0);
}
break;
@@ -1231,7 +1284,7 @@ static ssize_t hdmi_tx_sysfs_wta_s3d_mode(struct device *dev,
if (s3d_mode > HDMI_S3D_NONE &&
!hdmi_edid_is_s3d_mode_supported(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID],
+ hdmi_tx_get_fd(HDMI_TX_FEAT_EDID),
hdmi_ctrl->vid_cfg.vic,
s3d_mode)) {
DEV_ERR("%s: s3d mode not supported in current video mode\n",
@@ -1723,58 +1776,50 @@ end:
}
/* Enable HDMI features */
-static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl,
- struct fb_info *fbi)
+static int hdmi_tx_init_edid(struct hdmi_tx_ctrl *hdmi_ctrl)
{
struct hdmi_edid_init_data edid_init_data = {0};
- struct hdmi_hdcp_init_data hdcp_init_data = {0};
- struct hdmi_cec_init_data cec_init_data = {0};
- struct cec_abstract_init_data cec_abst_init_data = {0};
- struct hdmi_audio_init_data audio_init_data = {0};
- struct resource *res = NULL;
- void *fd = NULL;
- int ret = 0;
- void *cec_hw_data, *cec_abst_data;
-
- if (!hdmi_ctrl || !fbi) {
- DEV_ERR("%s: invalid input\n", __func__);
- ret = -EINVAL;
- goto end;
- }
+ void *edid_data;
+ int rc = 0;
- /* Initialize EDID feature */
edid_init_data.kobj = hdmi_ctrl->kobj;
edid_init_data.ds_data = hdmi_ctrl->ds_data;
edid_init_data.max_pclk_khz = hdmi_ctrl->max_pclk_khz;
- fd = hdmi_edid_init(&edid_init_data);
- if (!fd) {
- DEV_ERR("%s: hdmi_edid_init failed\n", __func__);
- ret = -ENODEV;
+ edid_data = hdmi_edid_init(&edid_init_data);
+ if (!edid_data) {
+ DEV_ERR("%s: edid init failed\n", __func__);
+ rc = -ENODEV;
goto end;
}
- hdmi_ctrl->panel_data.panel_info.edid_data = fd;
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID] = fd;
+ hdmi_ctrl->panel_data.panel_info.edid_data = edid_data;
+ hdmi_tx_set_fd(HDMI_TX_FEAT_EDID, edid_data);
/* get edid buffer from edid parser */
hdmi_ctrl->edid_buf = edid_init_data.buf;
hdmi_ctrl->edid_buf_size = edid_init_data.buf_size;
- hdmi_edid_set_video_resolution(fd, hdmi_ctrl->vid_cfg.vic, true);
+ hdmi_edid_set_video_resolution(edid_data, hdmi_ctrl->vid_cfg.vic, true);
+end:
+ return rc;
+}
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID] = fd;
+static int hdmi_tx_init_hdcp(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ struct hdmi_hdcp_init_data hdcp_init_data = {0};
+ struct resource *res;
+ void *hdcp_data;
+ int rc = 0;
res = platform_get_resource_byname(hdmi_ctrl->pdev,
IORESOURCE_MEM, hdmi_tx_io_name(HDMI_TX_CORE_IO));
if (!res) {
- DEV_ERR("%s: Error getting HDMI tx core resource\n",
- __func__);
- ret = -ENODEV;
- goto err_res;
+ DEV_ERR("%s: Error getting HDMI tx core resource\n", __func__);
+ rc = -EINVAL;
+ goto end;
}
- /* Initialize HDCP features */
hdcp_init_data.phy_addr = res->start;
hdcp_init_data.core_io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
hdcp_init_data.qfprom_io = &hdmi_ctrl->pdata.io[HDMI_TX_QFPROM_IO];
@@ -1789,30 +1834,38 @@ static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl,
hdcp_init_data.timing = &hdmi_ctrl->vid_cfg.timing;
if (hdmi_ctrl->hdcp14_present) {
- fd = hdmi_hdcp_init(&hdcp_init_data);
+ hdcp_data = hdmi_hdcp_init(&hdcp_init_data);
- if (IS_ERR_OR_NULL(fd)) {
- DEV_WARN("%s: hdmi_hdcp_init failed\n", __func__);
- ret = -ENODEV;
- goto err_res;
+ if (IS_ERR_OR_NULL(hdcp_data)) {
+ DEV_ERR("%s: hdcp 1.4 init failed\n", __func__);
+ rc = -EINVAL;
+ goto end;
} else {
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP] = fd;
- DEV_DBG("%s: HDCP 1.4 configured\n", __func__);
+ hdmi_tx_set_fd(HDMI_TX_FEAT_HDCP, hdcp_data);
+ DEV_DBG("%s: HDCP 1.4 initialized\n", __func__);
}
}
- fd = hdmi_hdcp2p2_init(&hdcp_init_data);
+ hdcp_data = hdmi_hdcp2p2_init(&hdcp_init_data);
- if (IS_ERR_OR_NULL(fd)) {
- DEV_WARN("%s: hdmi_hdcp2p2_init failed\n", __func__);
- ret = -ENODEV;
- goto err_hdcp;
+ if (IS_ERR_OR_NULL(hdcp_data)) {
+ DEV_ERR("%s: hdcp 2.2 init failed\n", __func__);
+ rc = -EINVAL;
+ goto end;
} else {
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2] = fd;
- DEV_DBG("%s: HDCP 2.2 configured\n", __func__);
+ hdmi_tx_set_fd(HDMI_TX_FEAT_HDCP2P2, hdcp_data);
+ DEV_DBG("%s: HDCP 2.2 initialized\n", __func__);
}
+end:
+ return rc;
+}
+
+static int hdmi_tx_init_cec_hw(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ struct hdmi_cec_init_data cec_init_data = {0};
+ void *cec_hw_data;
+ int rc = 0;
- /* initialize cec hw feature and get ops */
cec_init_data.io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
cec_init_data.workq = hdmi_ctrl->workq;
cec_init_data.pinfo = &hdmi_ctrl->panel_data.panel_info;
@@ -1821,53 +1874,153 @@ static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl,
cec_hw_data = hdmi_cec_init(&cec_init_data);
if (IS_ERR_OR_NULL(cec_hw_data)) {
- DEV_ERR("%s: error cec init\n", __func__);
- goto err_cec_hw;
+ DEV_ERR("%s: cec init failed\n", __func__);
+ rc = -EINVAL;
+ } else {
+ hdmi_ctrl->panel_data.panel_info.is_cec_supported = true;
+ hdmi_tx_set_fd(HDMI_TX_FEAT_CEC_HW, cec_hw_data);
+ DEV_DBG("%s: cec hw initialized\n", __func__);
}
- hdmi_ctrl->panel_data.panel_info.is_cec_supported = true;
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_HW] = cec_hw_data;
+ return rc;
+}
+
+static int hdmi_tx_init_cec_abst(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ struct cec_abstract_init_data cec_abst_init_data = {0};
+ void *cec_abst_data;
+ int rc = 0;
- /* initialize cec abstract layer and get callbacks */
cec_abst_init_data.kobj = hdmi_ctrl->kobj;
cec_abst_init_data.ops = &hdmi_ctrl->hdmi_cec_ops;
cec_abst_init_data.cbs = &hdmi_ctrl->hdmi_cec_cbs;
cec_abst_data = cec_abstract_init(&cec_abst_init_data);
if (IS_ERR_OR_NULL(cec_abst_data)) {
- DEV_ERR("%s: error cec init\n", __func__);
- goto err_cec_abst;
+ DEV_ERR("%s: cec abst init failed\n", __func__);
+ rc = -EINVAL;
+ } else {
+ hdmi_tx_set_fd(HDMI_TX_FEAT_CEC_ABST, cec_abst_data);
+ hdmi_ctrl->panel_data.panel_info.cec_data = cec_abst_data;
+ DEV_DBG("%s: cec abst initialized\n", __func__);
}
- /* keep cec abstract data */
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_ABST] = cec_abst_data;
- hdmi_ctrl->panel_data.panel_info.cec_data = cec_abst_data;
+ return rc;
+}
+
+static int hdmi_tx_init_audio(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ struct hdmi_audio_init_data audio_init_data = {0};
+ void *audio_data;
+ int rc = 0;
audio_init_data.io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
audio_init_data.ops = &hdmi_ctrl->audio_ops;
- hdmi_ctrl->audio_data = hdmi_audio_register(&audio_init_data);
- return 0;
+ audio_data = hdmi_audio_register(&audio_init_data);
+ if (!audio_data) {
+ rc = -EINVAL;
+ DEV_ERR("%s: audio init failed\n", __func__);
+ } else {
+ hdmi_ctrl->audio_data = audio_data;
+ DEV_DBG("%s: audio initialized\n", __func__);
+ }
-err_cec_abst:
- hdmi_cec_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_HW]);
- hdmi_ctrl->panel_data.panel_info.is_cec_supported = false;
-err_cec_hw:
- if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2]) {
- hdmi_hdcp2p2_deinit(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2]);
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2] = NULL;
- }
-err_hdcp:
- if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]) {
- hdmi_hdcp_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]);
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP] = NULL;
- }
-err_res:
- hdmi_edid_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]);
+ return rc;
+}
+
+static void hdmi_tx_deinit_features(struct hdmi_tx_ctrl *hdmi_ctrl,
+ u32 features)
+{
+ void *fd;
+
+ if (features & HDMI_TX_FEAT_CEC_ABST) {
+ fd = hdmi_tx_get_fd(HDMI_TX_FEAT_CEC_ABST);
+
+ cec_abstract_deinit(fd);
+
+ hdmi_ctrl->panel_data.panel_info.cec_data = NULL;
+ hdmi_tx_set_fd(HDMI_TX_FEAT_CEC_ABST, 0);
+ }
+
+ if (features & HDMI_TX_FEAT_CEC_HW) {
+ fd = hdmi_tx_get_fd(HDMI_TX_FEAT_CEC_HW);
+
+ hdmi_cec_deinit(fd);
+ hdmi_ctrl->panel_data.panel_info.is_cec_supported = false;
+ hdmi_tx_set_fd(HDMI_TX_FEAT_CEC_HW, 0);
+ }
+
+ if (features & HDMI_TX_FEAT_HDCP2P2) {
+ fd = hdmi_tx_get_fd(HDMI_TX_FEAT_HDCP2P2);
+
+ hdmi_hdcp2p2_deinit(fd);
+ hdmi_tx_set_fd(HDMI_TX_FEAT_HDCP2P2, 0);
+ }
+
+ if (features & HDMI_TX_FEAT_HDCP) {
+ fd = hdmi_tx_get_fd(HDMI_TX_FEAT_HDCP);
+
+ hdmi_hdcp_deinit(fd);
+ hdmi_tx_set_fd(HDMI_TX_FEAT_HDCP, 0);
+ }
+
+ if (features & HDMI_TX_FEAT_EDID) {
+ fd = hdmi_tx_get_fd(HDMI_TX_FEAT_EDID);
+
+ hdmi_edid_deinit(fd);
+ hdmi_ctrl->edid_buf = NULL;
+ hdmi_ctrl->edid_buf_size = 0;
+ hdmi_tx_set_fd(HDMI_TX_FEAT_EDID, 0);
+ }
+} /* hdmi_tx_init_features */
+
+static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl,
+ struct fb_info *fbi)
+{
+ int ret = 0;
+ u32 deinit_features = 0;
+
+ if (!hdmi_ctrl || !fbi) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ ret = -EINVAL;
+ goto end;
+ }
+
+ ret = hdmi_tx_init_edid(hdmi_ctrl);
+ if (ret)
+ goto end;
+
+ ret = hdmi_tx_init_hdcp(hdmi_ctrl);
+ if (ret) {
+ deinit_features |= HDMI_TX_FEAT_EDID;
+ goto err;
+ }
+
+ ret = hdmi_tx_init_cec_hw(hdmi_ctrl);
+ if (ret) {
+ deinit_features |= HDMI_TX_FEAT_HDCP;
+ goto err;
+ }
+
+ ret = hdmi_tx_init_cec_abst(hdmi_ctrl);
+ if (ret) {
+ deinit_features |= HDMI_TX_FEAT_CEC_HW;
+ goto err;
+ }
+
+ ret = hdmi_tx_init_audio(hdmi_ctrl);
+ if (ret) {
+ deinit_features |= HDMI_TX_FEAT_CEC_ABST;
+ goto err;
+ }
+
+ return 0;
+err:
+ hdmi_tx_deinit_features(hdmi_ctrl, deinit_features);
end:
return ret;
-} /* hdmi_tx_init_features */
+}
static inline u32 hdmi_tx_is_controller_on(struct hdmi_tx_ctrl *hdmi_ctrl)
{
@@ -1905,6 +2058,7 @@ static int hdmi_tx_init_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl)
pinfo->lcdc.v_back_porch = timing.back_porch_v;
pinfo->lcdc.v_front_porch = timing.front_porch_v;
pinfo->lcdc.v_pulse_width = timing.pulse_width_v;
+ pinfo->lcdc.frame_rate = timing.refresh_rate;
pinfo->type = DTV_PANEL;
pinfo->pdest = DISPLAY_3;
@@ -1912,6 +2066,9 @@ static int hdmi_tx_init_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl)
pinfo->bpp = 24;
pinfo->fb_num = 1;
+ pinfo->min_fps = HDMI_TX_MIN_FPS;
+ pinfo->max_fps = HDMI_TX_MAX_FPS;
+
pinfo->lcdc.border_clr = 0; /* blk */
pinfo->lcdc.underflow_clr = 0xff; /* blue */
pinfo->lcdc.hsync_skew = 0;
@@ -1932,7 +2089,7 @@ static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl)
return -EINVAL;
}
- data = hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID];
+ data = hdmi_tx_get_fd(HDMI_TX_FEAT_EDID);
if (!hdmi_tx_is_controller_on(hdmi_ctrl)) {
DEV_ERR("%s: failed: HDMI controller is off", __func__);
@@ -1972,7 +2129,7 @@ static void hdmi_tx_update_hdcp_info(struct hdmi_tx_ctrl *hdmi_ctrl)
}
/* check first if hdcp2p2 is supported */
- fd = hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2];
+ fd = hdmi_tx_get_fd(HDMI_TX_FEAT_HDCP2P2);
if (fd)
ops = hdmi_hdcp2p2_start(fd);
@@ -1987,7 +2144,7 @@ static void hdmi_tx_update_hdcp_info(struct hdmi_tx_ctrl *hdmi_ctrl)
hdcp1_check_if_supported_load_app();
if (hdmi_ctrl->hdcp14_present) {
- fd = hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP];
+ fd = hdmi_tx_get_fd(HDMI_TX_FEAT_HDCP);
ops = hdmi_hdcp_start(fd);
}
}
@@ -2105,6 +2262,18 @@ end:
return ret;
} /* hdmi_tx_check_capability */
+static void hdmi_tx_update_panel_data(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ struct mdss_panel_info *pinfo = &hdmi_ctrl->panel_data.panel_info;
+
+ pinfo->saved_total = mdss_panel_get_htotal(pinfo, true);
+ pinfo->saved_fporch = hdmi_ctrl->vid_cfg.timing.front_porch_h;
+
+ pinfo->current_fps = hdmi_ctrl->vid_cfg.timing.refresh_rate;
+ pinfo->default_fps = hdmi_ctrl->vid_cfg.timing.refresh_rate;
+ pinfo->lcdc.frame_rate = hdmi_ctrl->vid_cfg.timing.refresh_rate;
+}
+
static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl,
struct mdss_panel_info *pinfo)
{
@@ -2146,7 +2315,7 @@ static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl,
vid_cfg->vic = new_vic;
vid_cfg->avi_iframe.pixel_format = pinfo->out_format;
vid_cfg->avi_iframe.scan_info = hdmi_edid_get_sink_scaninfo(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID],
+ hdmi_tx_get_fd(HDMI_TX_FEAT_EDID),
hdmi_ctrl->vid_cfg.vic);
vid_cfg->avi_iframe.bar_info.end_of_top_bar = 0x0;
@@ -2180,12 +2349,30 @@ static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl,
(vid_cfg->timing.pixel_freq * 1000) >> div;
hdmi_edid_set_video_resolution(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID],
+ hdmi_tx_get_fd(HDMI_TX_FEAT_EDID),
vid_cfg->vic, false);
+ hdmi_tx_update_panel_data(hdmi_ctrl);
+
return res_changed;
} /* hdmi_tx_set_video_fmt */
+static bool hdmi_tx_check_for_video_update(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ struct msm_hdmi_mode_timing_info *timing = &hdmi_ctrl->vid_cfg.timing;
+ struct mdss_panel_info *pinfo = &hdmi_ctrl->panel_data.panel_info;
+
+ if (timing->back_porch_h != pinfo->lcdc.h_back_porch ||
+ timing->front_porch_h != pinfo->lcdc.h_front_porch ||
+ timing->pulse_width_h != pinfo->lcdc.h_pulse_width ||
+ timing->back_porch_v != pinfo->lcdc.v_back_porch ||
+ timing->front_porch_v != pinfo->lcdc.v_front_porch ||
+ timing->pulse_width_v != pinfo->lcdc.v_pulse_width)
+ return true;
+
+ return false;
+}
+
static int hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
{
u32 total_v = 0;
@@ -2197,6 +2384,7 @@ static int hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
u32 div = 0;
struct dss_io_data *io = NULL;
struct msm_hdmi_mode_timing_info *timing = NULL;
+ struct mdss_panel_info *pinfo;
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -2214,6 +2402,9 @@ static int hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
DEV_ERR("%s: Core io is not initialized\n", __func__);
return -EPERM;
}
+
+ pinfo = &hdmi_ctrl->panel_data.panel_info;
+
/*
* In case of YUV420 output, Horizontal timing parameters should be
* reduced by half
@@ -2221,6 +2412,35 @@ static int hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
if (hdmi_ctrl->vid_cfg.avi_iframe.pixel_format == MDP_Y_CBCR_H2V2)
div = 1;
+ if (pinfo->dynamic_fps) {
+ if (!hdmi_tx_check_for_video_update(hdmi_ctrl))
+ return -EINVAL;
+
+ if (pinfo->dfps_update ==
+ DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP ||
+ pinfo->dfps_update ==
+ DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) {
+ DEV_DBG("%s: hfp=%d, hbp=%d, hpw=%d\n", __func__,
+ pinfo->lcdc.h_front_porch,
+ pinfo->lcdc.h_back_porch,
+ pinfo->lcdc.h_pulse_width);
+
+ timing->back_porch_h = pinfo->lcdc.h_back_porch;
+ timing->front_porch_h = pinfo->lcdc.h_front_porch;
+ timing->pulse_width_h = pinfo->lcdc.h_pulse_width;
+ } else if (pinfo->dfps_update ==
+ DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) {
+ DEV_DBG("%s: vfp=%d, vbp=%d, vpw=%d\n", __func__,
+ pinfo->lcdc.v_front_porch,
+ pinfo->lcdc.v_back_porch,
+ pinfo->lcdc.v_pulse_width);
+
+ timing->back_porch_v = pinfo->lcdc.v_back_porch;
+ timing->front_porch_v = pinfo->lcdc.v_front_porch;
+ timing->pulse_width_v = pinfo->lcdc.v_pulse_width;
+ }
+ }
+
total_h = (hdmi_tx_get_h_total(timing) >> div) - 1;
total_v = hdmi_tx_get_v_total(timing) - 1;
@@ -2446,7 +2666,7 @@ static void hdmi_tx_set_vendor_specific_infoframe(
if ((hdmi_ctrl->s3d_mode != HDMI_S3D_NONE) &&
hdmi_edid_is_s3d_mode_supported(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID],
+ hdmi_tx_get_fd(HDMI_TX_FEAT_EDID),
hdmi_ctrl->vid_cfg.vic,
hdmi_ctrl->s3d_mode)) {
switch (hdmi_ctrl->s3d_mode) {
@@ -2650,8 +2870,7 @@ static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on)
reg_val |= BIT(2);
/* Set transmission mode to DVI based in EDID info */
- if (hdmi_edid_get_sink_mode(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) == 0)
+ if (!hdmi_edid_get_sink_mode(hdmi_tx_get_fd(HDMI_TX_FEAT_EDID)))
reg_val &= ~BIT(1); /* DVI mode */
/*
@@ -3113,7 +3332,7 @@ static int hdmi_tx_get_audio_edid_blk(struct platform_device *pdev,
}
return hdmi_edid_get_audio_blk(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], blk);
+ hdmi_tx_get_fd(HDMI_TX_FEAT_EDID), blk);
} /* hdmi_tx_get_audio_edid_blk */
static u8 hdmi_tx_tmds_enabled(struct platform_device *pdev)
@@ -3292,7 +3511,7 @@ int hdmi_tx_setup_scrambler(struct hdmi_tx_ctrl *hdmi_ctrl)
return -EINVAL;
}
- edid_data = hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID];
+ edid_data = hdmi_tx_get_fd(HDMI_TX_FEAT_EDID);
timing = &hdmi_ctrl->vid_cfg.timing;
if (!timing) {
@@ -3308,15 +3527,17 @@ int hdmi_tx_setup_scrambler(struct hdmi_tx_ctrl *hdmi_ctrl)
rate = hdmi_tx_setup_tmds_clk_rate(hdmi_ctrl);
- if (rate > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ) {
- scrambler_on = true;
- tmds_clock_ratio = 1;
- } else {
- if (hdmi_edid_get_sink_scrambler_support(edid_data))
+ scrambler_on = hdmi_edid_get_sink_scrambler_support(edid_data);
+
+ if (!hdmi_edid_sink_scramble_override(edid_data)) {
+ if (rate > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ)
scrambler_on = true;
}
if (scrambler_on) {
+ if (rate > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ)
+ tmds_clock_ratio = 1;
+
rc = hdmi_scdc_write(&hdmi_ctrl->ddc_ctrl,
HDMI_TX_SCDC_TMDS_BIT_CLOCK_RATIO_UPDATE,
tmds_clock_ratio);
@@ -3476,17 +3697,18 @@ static inline void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
sizeof(struct msm_ext_disp_audio_setup_params));
}
-static int hdmi_tx_power_off(struct mdss_panel_data *panel_data)
+static int hdmi_tx_power_off(struct hdmi_tx_ctrl *hdmi_ctrl)
{
struct dss_io_data *io = NULL;
- struct hdmi_tx_ctrl *hdmi_ctrl =
- hdmi_tx_get_drvdata_from_panel_data(panel_data);
+ struct mdss_panel_data *panel_data;
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
return -EINVAL;
}
+ panel_data = &hdmi_ctrl->panel_data;
+
io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
if (!io->base) {
DEV_ERR("%s: Core io is not initialized\n", __func__);
@@ -3522,14 +3744,13 @@ end:
return 0;
} /* hdmi_tx_power_off */
-static int hdmi_tx_power_on(struct mdss_panel_data *panel_data)
+static int hdmi_tx_power_on(struct hdmi_tx_ctrl *hdmi_ctrl)
{
int rc = 0;
int res_changed = RESOLUTION_UNCHANGED;
struct dss_io_data *io = NULL;
struct mdss_panel_info *panel_info = NULL;
- struct hdmi_tx_ctrl *hdmi_ctrl =
- hdmi_tx_get_drvdata_from_panel_data(panel_data);
+ struct mdss_panel_data *panel_data;
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -3548,6 +3769,8 @@ static int hdmi_tx_power_on(struct mdss_panel_data *panel_data)
goto end;
}
+ panel_data = &hdmi_ctrl->panel_data;
+
rc = hdmi_tx_check_clk_state(hdmi_ctrl, HDMI_TX_HPD_PM);
if (rc)
goto end;
@@ -3849,9 +4072,10 @@ static irqreturn_t hdmi_tx_isr(int irq, void *data)
hdmi_ctrl->hdmi_tx_ver))
DEV_ERR("%s: hdmi_ddc_isr failed\n", __func__);
- if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_HW])
- if (hdmi_cec_isr(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_HW]))
+ if (hdmi_tx_get_fd(HDMI_TX_FEAT_CEC_HW)) {
+ if (hdmi_cec_isr(hdmi_tx_get_fd(HDMI_TX_FEAT_CEC_HW)))
DEV_ERR("%s: hdmi_cec_isr failed\n", __func__);
+ }
if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_data) {
if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr) {
@@ -3872,37 +4096,11 @@ static void hdmi_tx_dev_deinit(struct hdmi_tx_ctrl *hdmi_ctrl)
return;
}
- if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_ABST]) {
- cec_abstract_deinit(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_ABST]);
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_ABST] = NULL;
- }
-
- if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_HW]) {
- hdmi_cec_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_HW]);
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC_HW] = NULL;
- hdmi_ctrl->panel_data.panel_info.is_cec_supported = false;
- }
-
- if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]) {
- hdmi_hdcp_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]);
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP] = NULL;
- }
-
- if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2]) {
- hdmi_hdcp2p2_deinit(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2]);
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2] = NULL;
- }
+ hdmi_tx_deinit_features(hdmi_ctrl, HDMI_TX_FEAT_MAX);
hdmi_ctrl->hdcp_ops = NULL;
hdmi_ctrl->hdcp_data = NULL;
- if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) {
- hdmi_edid_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]);
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID] = NULL;
- }
-
switch_dev_unregister(&hdmi_ctrl->sdev);
if (hdmi_ctrl->workq)
destroy_workqueue(hdmi_ctrl->workq);
@@ -3957,6 +4155,7 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl)
init_completion(&hdmi_ctrl->hpd_int_done);
INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work);
+ INIT_WORK(&hdmi_ctrl->fps_work, hdmi_tx_fps_work);
INIT_WORK(&hdmi_ctrl->cable_notify_work, hdmi_tx_cable_notify_work);
INIT_DELAYED_WORK(&hdmi_ctrl->hdcp_cb_work, hdmi_tx_hdcp_cb_work);
@@ -4088,212 +4287,379 @@ static char *hdmi_tx_get_event_name(int event)
}
}
-static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data,
- int event, void *arg)
+static void hdmi_tx_update_fps(struct hdmi_tx_ctrl *hdmi_ctrl)
{
- int rc = 0, new_vic = -1;
- struct hdmi_tx_ctrl *hdmi_ctrl =
- hdmi_tx_get_drvdata_from_panel_data(panel_data);
+ int rc = 0, vic = 0;
+ u64 pclk;
+ struct mdss_panel_data *pdata;
+ struct mdss_panel_info *pinfo;
+ struct msm_hdmi_mode_timing_info timing = {0};
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
- return -EINVAL;
+ return;
}
- mutex_lock(&hdmi_ctrl->tx_lock);
+ pdata = &hdmi_ctrl->panel_data;
+ pinfo = &pdata->panel_info;
- DEV_DBG("%s: event = %s suspend=%d, hpd_feature=%d\n", __func__,
- hdmi_tx_get_event_name(event), hdmi_ctrl->panel_suspend,
- hdmi_ctrl->hpd_feature_on);
+ if (!pinfo->dynamic_fps) {
+ DEV_DBG("%s: Dynamic fps not enabled\n", __func__);
+ return;
+ }
- switch (event) {
- case MDSS_EVENT_FB_REGISTERED:
- rc = hdmi_tx_sysfs_create(hdmi_ctrl, arg);
- if (rc) {
- DEV_ERR("%s: hdmi_tx_sysfs_create failed.rc=%d\n",
- __func__, rc);
- goto end;
- }
- rc = hdmi_tx_init_features(hdmi_ctrl, arg);
- if (rc) {
- DEV_ERR("%s: init_features failed.rc=%d\n",
- __func__, rc);
- hdmi_tx_sysfs_remove(hdmi_ctrl);
- goto end;
+ if (hdmi_ctrl->dynamic_fps == pinfo->current_fps) {
+ DEV_DBG("%s: Panel is already at this FPS: %d\n",
+ __func__, hdmi_ctrl->dynamic_fps);
+ return;
+ }
+
+ if (hdmi_tx_is_hdcp_enabled(hdmi_ctrl))
+ hdmi_tx_hdcp_off(hdmi_ctrl);
+
+ if (pinfo->dfps_update == DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) {
+ if (hdmi_tx_video_setup(hdmi_ctrl)) {
+ DEV_DBG("%s: no change in video timing\n", __func__);
+ return;
}
- rc = hdmi_tx_init_switch_dev(hdmi_ctrl);
- if (rc) {
- DEV_ERR("%s: init switch dev failed.rc=%d\n",
- __func__, rc);
- hdmi_tx_sysfs_remove(hdmi_ctrl);
- goto end;
+ if (hdmi_tx_update_pixel_clk(hdmi_ctrl,
+ hdmi_ctrl->dynamic_fps)) {
+ DEV_DBG("%s: no change in clk\n", __func__);
+ return;
}
- if (hdmi_ctrl->pdata.primary || !hdmi_ctrl->pdata.pluggable) {
- reinit_completion(&hdmi_ctrl->hpd_int_done);
- rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
- if (rc) {
- DEV_ERR("%s: hpd_enable failed. rc=%d\n",
- __func__, rc);
- hdmi_tx_sysfs_remove(hdmi_ctrl);
- goto end;
- } else {
- hdmi_ctrl->hpd_feature_on = true;
- }
+ pinfo->saved_total = mdss_panel_get_htotal(pinfo, true);
+ pinfo->saved_fporch = pinfo->lcdc.h_front_porch;
+ } else if (pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP) {
+ if (hdmi_tx_video_setup(hdmi_ctrl)) {
+ DEV_DBG("%s: no change in video timing\n", __func__);
+ return;
}
- break;
+ pinfo->saved_total = mdss_panel_get_htotal(pinfo, true);
+ pinfo->saved_fporch = pinfo->lcdc.h_front_porch;
+ } else if (pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) {
+ if (hdmi_tx_video_setup(hdmi_ctrl)) {
+ DEV_DBG("%s: no change in video timing\n", __func__);
+ return;
+ }
- case MDSS_EVENT_CHECK_PARAMS:
- new_vic = hdmi_tx_get_vic_from_panel_info(hdmi_ctrl,
- (struct mdss_panel_info *)arg);
- if ((new_vic < 0) || (new_vic > HDMI_VFRMT_MAX)) {
- DEV_ERR("%s: invalid or not supported vic\n", __func__);
- goto end;
+ pinfo->saved_total = mdss_panel_get_vtotal(pinfo);
+ pinfo->saved_fporch = pinfo->lcdc.v_front_porch;
+ } else if (pinfo->dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) {
+ if (hdmi_tx_update_pixel_clk(hdmi_ctrl,
+ hdmi_ctrl->dynamic_fps)) {
+ DEV_DBG("%s: no change in clk\n", __func__);
+ return;
}
+ }
- /*
- * return value of 1 lets mdss know that panel
- * needs a reconfig due to new resolution and
- * it will issue close and open subsequently.
- */
- if (new_vic != hdmi_ctrl->vid_cfg.vic)
- rc = 1;
- else
- DEV_DBG("%s: no res change.\n", __func__);
- break;
+ pinfo->current_fps = hdmi_ctrl->dynamic_fps;
+ pinfo->default_fps = hdmi_ctrl->dynamic_fps;
+ pinfo->lcdc.frame_rate = hdmi_ctrl->dynamic_fps;
+ pinfo->dynamic_fps = false;
- case MDSS_EVENT_RESUME:
- hdmi_ctrl->panel_suspend = false;
- hdmi_tx_cec_device_suspend(hdmi_ctrl, hdmi_ctrl->panel_suspend);
+ rc = hdmi_get_supported_mode(&timing, &hdmi_ctrl->ds_data,
+ hdmi_ctrl->vid_cfg.vic);
- if (!hdmi_ctrl->hpd_feature_on)
- goto end;
+ if (rc || !timing.supported) {
+ DEV_ERR("%s: timing details\n", __func__);
+ return;
+ }
- rc = hdmi_tx_hpd_on(hdmi_ctrl);
- if (rc) {
- DEV_ERR("%s: hpd_on failed. rc=%d\n", __func__, rc);
- goto end;
- }
+ timing.back_porch_h = pinfo->lcdc.h_back_porch;
+ timing.front_porch_h = pinfo->lcdc.h_front_porch;
+ timing.pulse_width_h = pinfo->lcdc.h_pulse_width;
- if (hdmi_ctrl->sdev.state &&
- !hdmi_tx_hw_is_cable_connected(hdmi_ctrl)) {
- u32 timeout;
-
- reinit_completion(&hdmi_ctrl->hpd_int_done);
- timeout = wait_for_completion_timeout(
- &hdmi_ctrl->hpd_int_done, HZ/10);
- if (!timeout && !hdmi_ctrl->hpd_state) {
- DEV_DBG("%s: cable removed during suspend\n",
- __func__);
- hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0);
- hdmi_tx_wait_for_audio_engine(hdmi_ctrl);
- hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
- }
- }
+ timing.back_porch_v = pinfo->lcdc.v_back_porch;
+ timing.front_porch_v = pinfo->lcdc.v_front_porch;
+ timing.pulse_width_v = pinfo->lcdc.v_pulse_width;
- break;
+ timing.refresh_rate = hdmi_ctrl->dynamic_fps;
- case MDSS_EVENT_RESET:
- if (!hdmi_ctrl->pdata.cont_splash_enabled &&
- hdmi_ctrl->hpd_initialized) {
- hdmi_tx_set_mode(hdmi_ctrl, false);
- hdmi_tx_phy_reset(hdmi_ctrl);
- hdmi_tx_set_mode(hdmi_ctrl, true);
- }
+ pclk = pinfo->clk_rate;
+ do_div(pclk, HDMI_TX_KHZ_TO_HZ);
+ timing.pixel_freq = (unsigned long) pclk;
- break;
+ hdmi_ctrl->vid_cfg.timing = timing;
- case MDSS_EVENT_UNBLANK:
- rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, true);
+ vic = hdmi_get_video_id_code(&timing, &hdmi_ctrl->ds_data);
+
+ if (vic > 0 && hdmi_ctrl->vid_cfg.vic != vic) {
+ hdmi_ctrl->vid_cfg.vic = vic;
+ DEV_DBG("%s: switched to new resolution id %d\n",
+ __func__, vic);
+ }
+
+ hdmi_tx_start_hdcp(hdmi_ctrl);
+}
+
+static void hdmi_tx_fps_work(struct work_struct *work)
+{
+ struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+
+ hdmi_ctrl = container_of(work, struct hdmi_tx_ctrl, fps_work);
+ if (!hdmi_ctrl) {
+ DEV_DBG("%s: invalid input\n", __func__);
+ return;
+ }
+
+ hdmi_tx_update_fps(hdmi_ctrl);
+}
+
+static int hdmi_tx_evt_handle_register(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ int rc = 0;
+
+ rc = hdmi_tx_sysfs_create(hdmi_ctrl, hdmi_ctrl->evt_arg);
+ if (rc) {
+ DEV_ERR("%s: hdmi_tx_sysfs_create failed.rc=%d\n",
+ __func__, rc);
+ goto sysfs_err;
+ }
+ rc = hdmi_tx_init_features(hdmi_ctrl, hdmi_ctrl->evt_arg);
+ if (rc) {
+ DEV_ERR("%s: init_features failed.rc=%d\n", __func__, rc);
+ goto init_err;
+ }
+
+ rc = hdmi_tx_init_switch_dev(hdmi_ctrl);
+ if (rc) {
+ DEV_ERR("%s: init switch dev failed.rc=%d\n", __func__, rc);
+ goto switch_err;
+ }
+
+ if (hdmi_ctrl->pdata.primary || !hdmi_ctrl->pdata.pluggable) {
+ reinit_completion(&hdmi_ctrl->hpd_int_done);
+ rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
if (rc) {
- DEV_ERR("%s: ddc power on failed. rc=%d\n",
- __func__, rc);
+ DEV_ERR("%s: hpd_enable failed. rc=%d\n", __func__, rc);
+ goto primary_err;
} else {
- rc = hdmi_tx_power_on(panel_data);
- if (rc)
- DEV_ERR("%s: hdmi_tx_power_on failed. rc=%d\n",
- __func__, rc);
+ hdmi_ctrl->hpd_feature_on = true;
}
- break;
+ }
- case MDSS_EVENT_PANEL_ON:
- if (!hdmi_ctrl->sim_mode) {
- hdmi_tx_update_hdcp_info(hdmi_ctrl);
+ return 0;
- rc = hdmi_tx_start_hdcp(hdmi_ctrl);
- if (rc)
- DEV_ERR("%s: hdcp start failed rc=%d\n",
- __func__, rc);
- }
+primary_err:
+ switch_dev_unregister(&hdmi_ctrl->sdev);
+switch_err:
+ hdmi_tx_deinit_features(hdmi_ctrl, HDMI_TX_FEAT_MAX);
+init_err:
+ hdmi_tx_sysfs_remove(hdmi_ctrl);
+sysfs_err:
+ return rc;
+}
- hdmi_ctrl->timing_gen_on = true;
+static int hdmi_tx_evt_handle_check_param(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ int new_vic = -1;
+ int rc = 0;
- if (hdmi_ctrl->panel_suspend) {
- DEV_DBG("%s: panel suspend has triggered\n", __func__);
+ new_vic = hdmi_tx_get_vic_from_panel_info(hdmi_ctrl,
+ hdmi_ctrl->evt_arg);
+ if ((new_vic < 0) || (new_vic > HDMI_VFRMT_MAX)) {
+ DEV_ERR("%s: invalid or not supported vic\n", __func__);
+ goto end;
+ }
+ /*
+ * return value of 1 lets mdss know that panel
+ * needs a reconfig due to new resolution and
+ * it will issue close and open subsequently.
+ */
+ if (new_vic != hdmi_ctrl->vid_cfg.vic) {
+ rc = 1;
+ DEV_DBG("%s: res change %d ==> %d\n", __func__,
+ hdmi_ctrl->vid_cfg.vic, new_vic);
+ }
+end:
+ return rc;
+}
+
+static int hdmi_tx_evt_handle_resume(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ int rc = 0;
+
+ hdmi_ctrl->panel_suspend = false;
+ hdmi_tx_cec_device_suspend(hdmi_ctrl);
+
+ if (!hdmi_ctrl->hpd_feature_on)
+ goto end;
+
+ rc = hdmi_tx_hpd_on(hdmi_ctrl);
+ if (rc) {
+ DEV_ERR("%s: hpd_on failed. rc=%d\n", __func__, rc);
+ goto end;
+ }
+
+ if (hdmi_ctrl->sdev.state &&
+ !hdmi_tx_hw_is_cable_connected(hdmi_ctrl)) {
+ u32 timeout;
+
+ reinit_completion(&hdmi_ctrl->hpd_int_done);
+ timeout = wait_for_completion_timeout(
+ &hdmi_ctrl->hpd_int_done, HZ/10);
+ if (!timeout && !hdmi_ctrl->hpd_state) {
+ DEV_DBG("%s: cable removed during suspend\n", __func__);
hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0);
hdmi_tx_wait_for_audio_engine(hdmi_ctrl);
hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
}
- break;
+ }
+end:
+ return rc;
+}
- case MDSS_EVENT_SUSPEND:
- if (!hdmi_ctrl->hpd_feature_on)
- goto end;
+static int hdmi_tx_evt_handle_reset(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ if (!hdmi_ctrl->panel_data.panel_info.cont_splash_enabled &&
+ hdmi_ctrl->hpd_initialized) {
+ hdmi_tx_set_mode(hdmi_ctrl, false);
+ hdmi_tx_phy_reset(hdmi_ctrl);
+ hdmi_tx_set_mode(hdmi_ctrl, true);
+ }
- if (!hdmi_ctrl->hpd_state && !hdmi_ctrl->panel_power_on)
- hdmi_tx_hpd_off(hdmi_ctrl);
+ return 0;
+}
- hdmi_ctrl->panel_suspend = true;
- hdmi_tx_cec_device_suspend(hdmi_ctrl, hdmi_ctrl->panel_suspend);
- break;
+static int hdmi_tx_evt_handle_unblank(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ int rc;
- case MDSS_EVENT_BLANK:
- if (hdmi_tx_is_hdcp_enabled(hdmi_ctrl))
- hdmi_tx_hdcp_off(hdmi_ctrl);
+ rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, true);
+ if (rc) {
+ DEV_ERR("%s: ddc power on failed. rc=%d\n", __func__, rc);
+ goto end;
+ }
- break;
+ rc = hdmi_tx_power_on(hdmi_ctrl);
+ if (rc)
+ DEV_ERR("%s: hdmi_tx_power_on failed. rc=%d\n", __func__, rc);
+end:
+ return rc;
+}
- case MDSS_EVENT_PANEL_OFF:
- rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false);
- if (rc) {
- DEV_ERR("%s: Failed to disable ddc power\n", __func__);
- return rc;
- }
+static int hdmi_tx_evt_handle_panel_on(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ int rc = 0;
- if (hdmi_ctrl->panel_power_on) {
- hdmi_tx_config_avmute(hdmi_ctrl, 1);
- rc = hdmi_tx_power_off(panel_data);
- if (rc)
- DEV_ERR("%s: hdmi_tx_power_off failed.rc=%d\n",
- __func__, rc);
- } else {
- DEV_DBG("%s: hdmi is already powered off\n", __func__);
- }
+ if (!hdmi_ctrl->sim_mode) {
+ hdmi_tx_update_hdcp_info(hdmi_ctrl);
- hdmi_ctrl->timing_gen_on = false;
- break;
+ rc = hdmi_tx_start_hdcp(hdmi_ctrl);
+ if (rc)
+ DEV_ERR("%s: hdcp start failed rc=%d\n", __func__, rc);
+ }
- case MDSS_EVENT_CLOSE:
- if (panel_data->panel_info.cont_splash_enabled) {
- hdmi_tx_power_off(panel_data);
- panel_data->panel_info.cont_splash_enabled = false;
+ hdmi_ctrl->timing_gen_on = true;
- goto end;
- }
+ if (hdmi_ctrl->panel_suspend) {
+ DEV_DBG("%s: panel suspend has triggered\n", __func__);
- if (hdmi_ctrl->hpd_feature_on && hdmi_ctrl->hpd_initialized &&
- !hdmi_ctrl->hpd_state)
- hdmi_tx_hpd_polarity_setup(hdmi_ctrl,
- HPD_CONNECT_POLARITY);
- break;
+ hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0);
+ hdmi_tx_wait_for_audio_engine(hdmi_ctrl);
+ hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
+ }
+
+ return rc;
+}
+
+static int hdmi_tx_evt_handle_suspend(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ if (!hdmi_ctrl->hpd_feature_on)
+ goto end;
+
+ if (!hdmi_ctrl->hpd_state && !hdmi_ctrl->panel_power_on)
+ hdmi_tx_hpd_off(hdmi_ctrl);
+
+ hdmi_ctrl->panel_suspend = true;
+ hdmi_tx_cec_device_suspend(hdmi_ctrl);
+end:
+ return 0;
+}
+
+static int hdmi_tx_evt_handle_blank(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ if (hdmi_tx_is_hdcp_enabled(hdmi_ctrl))
+ hdmi_tx_hdcp_off(hdmi_ctrl);
+
+ return 0;
+}
+
+static int hdmi_tx_evt_handle_panel_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ int rc;
+
+ rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false);
+ if (rc) {
+ DEV_ERR("%s: Failed to disable ddc power\n", __func__);
+ goto end;
}
+
+ if (hdmi_ctrl->panel_power_on) {
+ hdmi_tx_config_avmute(hdmi_ctrl, 1);
+ rc = hdmi_tx_power_off(hdmi_ctrl);
+ if (rc)
+ DEV_ERR("%s: hdmi_tx_power_off failed.rc=%d\n",
+ __func__, rc);
+ } else {
+ DEV_DBG("%s: hdmi_ctrl is already powered off\n", __func__);
+ }
+
+ hdmi_ctrl->timing_gen_on = false;
end:
+ return rc;
+}
+
+static int hdmi_tx_evt_handle_close(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ if (hdmi_ctrl->hpd_feature_on && hdmi_ctrl->hpd_initialized &&
+ !hdmi_ctrl->hpd_state)
+ hdmi_tx_hpd_polarity_setup(hdmi_ctrl, HPD_CONNECT_POLARITY);
+
+ return 0;
+}
+
+static int hdmi_tx_event_handler(struct mdss_panel_data *panel_data,
+ int event, void *arg)
+{
+ int rc = 0;
+ hdmi_tx_evt_handler handler;
+ struct hdmi_tx_ctrl *hdmi_ctrl =
+ hdmi_tx_get_drvdata_from_panel_data(panel_data);
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ rc = -EINVAL;
+ goto end;
+ }
+
+ /* UPDATE FPS is called from atomic context */
+ if (event == MDSS_EVENT_PANEL_UPDATE_FPS) {
+ hdmi_ctrl->dynamic_fps = (u32) (unsigned long)arg;
+ queue_work(hdmi_ctrl->workq, &hdmi_ctrl->fps_work);
+ return rc;
+ }
+
+ mutex_lock(&hdmi_ctrl->tx_lock);
+
+ hdmi_ctrl->evt_arg = arg;
+
+ DEV_DBG("%s: event = %s suspend=%d, hpd_feature=%d\n", __func__,
+ hdmi_tx_get_event_name(event), hdmi_ctrl->panel_suspend,
+ hdmi_ctrl->hpd_feature_on);
+
+ handler = hdmi_ctrl->evt_handler[event];
+ if (handler)
+ rc = handler(hdmi_ctrl);
+
mutex_unlock(&hdmi_ctrl->tx_lock);
+end:
return rc;
-} /* hdmi_tx_panel_event_handler */
+}
static int hdmi_tx_register_panel(struct hdmi_tx_ctrl *hdmi_ctrl)
{
@@ -4304,7 +4670,7 @@ static int hdmi_tx_register_panel(struct hdmi_tx_ctrl *hdmi_ctrl)
return -EINVAL;
}
- hdmi_ctrl->panel_data.event_handler = hdmi_tx_panel_event_handler;
+ hdmi_ctrl->panel_data.event_handler = hdmi_tx_event_handler;
if (!hdmi_ctrl->pdata.primary)
hdmi_ctrl->vid_cfg.vic = DEFAULT_VIDEO_RESOLUTION;
@@ -4894,6 +5260,29 @@ error:
return rc;
} /* hdmi_tx_get_dt_data */
+static int hdmi_tx_init_event_handler(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ hdmi_tx_evt_handler *handler;
+
+ if (!hdmi_ctrl)
+ return -EINVAL;
+
+ handler = hdmi_ctrl->evt_handler;
+
+ handler[MDSS_EVENT_FB_REGISTERED] = hdmi_tx_evt_handle_register;
+ handler[MDSS_EVENT_CHECK_PARAMS] = hdmi_tx_evt_handle_check_param;
+ handler[MDSS_EVENT_RESUME] = hdmi_tx_evt_handle_resume;
+ handler[MDSS_EVENT_RESET] = hdmi_tx_evt_handle_reset;
+ handler[MDSS_EVENT_UNBLANK] = hdmi_tx_evt_handle_unblank;
+ handler[MDSS_EVENT_PANEL_ON] = hdmi_tx_evt_handle_panel_on;
+ handler[MDSS_EVENT_SUSPEND] = hdmi_tx_evt_handle_suspend;
+ handler[MDSS_EVENT_BLANK] = hdmi_tx_evt_handle_blank;
+ handler[MDSS_EVENT_PANEL_OFF] = hdmi_tx_evt_handle_panel_off;
+ handler[MDSS_EVENT_CLOSE] = hdmi_tx_evt_handle_close;
+
+ return 0;
+}
+
static int hdmi_tx_probe(struct platform_device *pdev)
{
int rc = 0, i;
@@ -4975,6 +5364,13 @@ static int hdmi_tx_probe(struct platform_device *pdev)
goto failed_dev_init;
}
+ rc = hdmi_tx_init_event_handler(hdmi_ctrl);
+ if (rc) {
+ DEV_ERR("%s: FAILED: hdmi_tx_init_event_handler. rc=%d\n",
+ __func__, rc);
+ goto failed_dev_init;
+ }
+
rc = hdmi_tx_register_panel(hdmi_ctrl);
if (rc) {
DEV_ERR("%s: FAILED: register_panel. rc=%d\n", __func__, rc);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.h b/drivers/video/fbdev/msm/mdss_hdmi_tx.h
index a33ed2d4a3d1..f348bfba6929 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.h
@@ -121,6 +121,9 @@ struct hdmi_video_config {
struct hdmi_avi_infoframe_config avi_iframe;
};
+struct hdmi_tx_ctrl;
+typedef int (*hdmi_tx_evt_handler) (struct hdmi_tx_ctrl *);
+
struct hdmi_tx_ctrl {
struct platform_device *pdev;
u32 hdmi_tx_ver;
@@ -150,6 +153,7 @@ struct hdmi_tx_ctrl {
u32 hpd_feature_on;
u32 hpd_initialized;
u32 vote_hdmi_core_on;
+ u32 dynamic_fps;
u8 timing_gen_on;
u8 mhl_hpd_on;
u8 hdcp_status;
@@ -157,6 +161,7 @@ struct hdmi_tx_ctrl {
struct hdmi_util_ds_data ds_data;
struct completion hpd_int_done;
struct work_struct hpd_int_work;
+ struct work_struct fps_work;
struct delayed_work hdcp_cb_work;
struct work_struct cable_notify_work;
@@ -182,7 +187,7 @@ struct hdmi_tx_ctrl {
void *downstream_data;
void *audio_data;
- void *feature_data[HDMI_TX_FEAT_MAX];
+ void *feature_data[hweight8(HDMI_TX_FEAT_MAX)];
struct hdmi_hdcp_ops *hdcp_ops;
void *hdcp_data;
bool hdcp22_present;
@@ -198,6 +203,9 @@ struct hdmi_tx_ctrl {
char disp_switch_name[MAX_SWITCH_NAME_SIZE];
bool power_data_enable[HDMI_TX_MAX_PM];
+
+ hdmi_tx_evt_handler evt_handler[MDSS_EVENT_MAX];
+ void *evt_arg;
};
#endif /* __MDSS_HDMI_TX_H__ */
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.c b/drivers/video/fbdev/msm/mdss_hdmi_util.c
index 4640c3f505b6..555ba1ba5b1c 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_util.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_util.c
@@ -595,29 +595,13 @@ int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in,
break;
}
- if (vic < 0) {
- for (i = 0; i < HDMI_VFRMT_MAX; i++) {
- ret = hdmi_get_supported_mode(&supported_timing,
- ds_data, i);
- if (ret || !supported_timing.supported)
- continue;
- if (timing_in->active_h != supported_timing.active_h)
- continue;
- if (timing_in->active_v != supported_timing.active_v)
- continue;
- vic = (int)supported_timing.video_format;
- break;
- }
- }
-
- if (vic < 0) {
+ if (vic < 0)
pr_err("timing is not supported h=%d v=%d\n",
timing_in->active_h, timing_in->active_v);
- }
-
+ else
+ pr_debug("vic = %d timing = %s\n", vic,
+ msm_hdmi_mode_2string((u32)vic));
exit:
- pr_debug("vic = %d timing = %s\n", vic,
- msm_hdmi_mode_2string((u32)vic));
return vic;
} /* hdmi_get_video_id_code */
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.h b/drivers/video/fbdev/msm/mdss_hdmi_util.h
index cb459ab17bd7..cbe22b751e77 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_util.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_util.h
@@ -368,12 +368,14 @@
#define HDMI_DEFAULT_TIMEOUT_HSYNC 28571
enum hdmi_tx_feature_type {
- HDMI_TX_FEAT_EDID,
- HDMI_TX_FEAT_HDCP,
- HDMI_TX_FEAT_HDCP2P2,
- HDMI_TX_FEAT_CEC_HW,
- HDMI_TX_FEAT_CEC_ABST,
- HDMI_TX_FEAT_MAX,
+ HDMI_TX_FEAT_EDID = BIT(0),
+ HDMI_TX_FEAT_HDCP = BIT(1),
+ HDMI_TX_FEAT_HDCP2P2 = BIT(2),
+ HDMI_TX_FEAT_CEC_HW = BIT(3),
+ HDMI_TX_FEAT_CEC_ABST = BIT(4),
+ HDMI_TX_FEAT_MAX = HDMI_TX_FEAT_EDID | HDMI_TX_FEAT_HDCP |
+ HDMI_TX_FEAT_HDCP2P2 | HDMI_TX_FEAT_CEC_HW |
+ HDMI_TX_FEAT_CEC_ABST
};
enum hdmi_tx_scdc_access_type {
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index 8e51aaf31b93..e2743353acd1 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -114,7 +114,7 @@ struct mdss_hw mdss_misc_hw = {
.irq_handler = NULL,
};
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef CONFIG_QCOM_BUS_SCALING
#define MDP_REG_BUS_VECTOR_ENTRY(ab_val, ib_val) \
{ \
.src = MSM_BUS_MASTER_AMPSS_M0, \
@@ -387,7 +387,7 @@ static irqreturn_t mdss_irq_handler(int irq, void *ptr)
return IRQ_HANDLED;
}
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef CONFIG_QCOM_BUS_SCALING
static int mdss_mdp_bus_scale_register(struct mdss_data_type *mdata)
{
struct msm_bus_scale_pdata *reg_bus_pdata;
@@ -2275,6 +2275,9 @@ ssize_t mdss_mdp_show_capabilities(struct device *dev,
SPRINT("max_downscale_ratio=%d\n", MAX_DOWNSCALE_RATIO);
SPRINT("max_upscale_ratio=%d\n", MAX_UPSCALE_RATIO);
+ if (mdata->nwb)
+ SPRINT("wb_intf_index=%d\n", mdata->nwb - 1);
+
if (test_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map)) {
SPRINT("fmt_mt_nv12_factor=%d\n",
mdata->prefill_data.prefill_factors.fmt_mt_nv12_factor);
@@ -4122,7 +4125,7 @@ static int mdss_mdp_parse_dt_ppb_off(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef CONFIG_QCOM_BUS_SCALING
static int mdss_mdp_parse_dt_bus_scale(struct platform_device *pdev)
{
int rc, paths;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 180730d48c57..d409618ae6c0 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -5656,7 +5656,7 @@ static int mdss_mdp_scaler_lut_init(struct mdss_data_type *mdata,
struct mdp_scale_luts_info *lut_tbl)
{
struct mdss_mdp_qseed3_lut_tbl *qseed3_lut_tbl;
- int ret;
+ int ret = 0;
if (!mdata->scaler_off)
return -EFAULT;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c
index a87e5d11b4a6..9c8b6684e1b3 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c
@@ -1626,6 +1626,11 @@ int mdss_mdp_qseed3_setup(struct mdss_mdp_pipe *pipe,
return -EINVAL;
}
+ if (!scaler) {
+ pr_debug("scaler pointer is NULL\n");
+ return 0;
+ }
+
pr_debug("scaler->enable=%d", scaler->enable);
op_mode = readl_relaxed(MDSS_MDP_REG_SCALER_OP_MODE +
offset);
@@ -1742,17 +1747,21 @@ int mdss_mdp_qseed3_setup(struct mdss_mdp_pipe *pipe,
return rc;
}
-static int mdss_mdp_scale_setup(struct mdss_mdp_pipe *pipe)
+static int mdss_mdp_scale_setup(struct mdss_mdp_pipe *pipe,
+ enum pp_config_block pp_blk)
{
struct mdss_data_type *mdata;
int rc = 0;
mdata = mdss_mdp_get_mdata();
if (test_bit(MDSS_CAPS_QSEED3, mdata->mdss_caps_map))
- rc = mdss_mdp_qseed3_setup(pipe, SSPP_VIG, 0);
+ rc = mdss_mdp_qseed3_setup(pipe, pp_blk, 0);
else
rc = mdss_mdp_qseed2_setup(pipe);
+ if (rc)
+ pr_err("scale setup on pipe %d type %d failed ret %d\n",
+ pipe->num, pipe->type, rc);
return rc;
}
@@ -1762,18 +1771,17 @@ int mdss_mdp_pipe_pp_setup(struct mdss_mdp_pipe *pipe, u32 *op)
if (!pipe)
return -ENODEV;
- ret = mdss_mdp_scale_setup(pipe);
- if (ret) {
- pr_err("scale setup on pipe %d type %d failed ret %d\n",
- pipe->num, pipe->type, ret);
- return -EINVAL;
- }
-
switch (pipe->type) {
case MDSS_MDP_PIPE_TYPE_VIG:
+ ret = mdss_mdp_scale_setup(pipe, SSPP_VIG);
+ if (ret)
+ return -EINVAL;
ret = pp_vig_pipe_setup(pipe, op);
break;
case MDSS_MDP_PIPE_TYPE_RGB:
+ ret = mdss_mdp_scale_setup(pipe, SSPP_RGB);
+ if (ret)
+ return -EINVAL;
ret = pp_rgb_pipe_setup(pipe, op);
break;
case MDSS_MDP_PIPE_TYPE_DMA:
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 7528f642149b..d3f836032bb6 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -262,6 +262,7 @@ enum mdss_intf_events {
MDSS_EVENT_DSI_RECONFIG_CMD,
MDSS_EVENT_DSI_RESET_WRITE_PTR,
MDSS_EVENT_PANEL_TIMING_SWITCH,
+ MDSS_EVENT_MAX,
};
struct lcd_panel_info {
diff --git a/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h b/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h
index 2c92246827b6..d637d123e714 100644
--- a/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h
+++ b/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h
@@ -125,6 +125,7 @@
#define GCC_AGGRE1_USB3_AXI_CBCR 0x82024
#define GCC_BIMC_MSS_Q6_AXI_CBCR 0x4401C
#define GCC_BLSP1_AHB_CBCR 0x17004
+#define GCC_BLSP1_BCR 0x17000
#define GCC_BLSP1_QUP1_SPI_APPS_CBCR 0x19004
#define GCC_BLSP1_QUP1_I2C_APPS_CBCR 0x19008
#define GCC_BLSP1_QUP2_SPI_APPS_CBCR 0x1B004
@@ -141,6 +142,7 @@
#define GCC_BLSP1_UART2_APPS_CBCR 0x1C004
#define GCC_BLSP1_UART3_APPS_CBCR 0x1E004
#define GCC_BLSP2_AHB_CBCR 0x25004
+#define GCC_BLSP2_BCR 0x25000
#define GCC_BLSP2_QUP1_SPI_APPS_CBCR 0x26004
#define GCC_BLSP2_QUP1_I2C_APPS_CBCR 0x26008
#define GCC_BLSP2_QUP2_I2C_APPS_CBCR 0x28008
@@ -195,6 +197,7 @@
#define GCC_TSIF_AHB_CBCR 0x36004
#define GCC_TSIF_REF_CBCR 0x36008
#define GCC_UFS_AXI_CBCR 0x75008
+#define GCC_UFS_BCR 0x75000
#define GCC_UFS_AHB_CBCR 0x7500C
#define GCC_UFS_TX_SYMBOL_0_CBCR 0x75010
#define GCC_UFS_RX_SYMBOL_0_CBCR 0x75014
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 5ad9cf84a581..bc7ad2e61018 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -391,6 +391,7 @@ extern void scheduler_tick(void);
extern void sched_show_task(struct task_struct *p);
#ifdef CONFIG_LOCKUP_DETECTOR
+extern void touch_softlockup_watchdog_sched(void);
extern void touch_softlockup_watchdog(void);
extern void touch_softlockup_watchdog_sync(void);
extern void touch_all_softlockup_watchdogs(void);
@@ -401,6 +402,9 @@ extern unsigned int softlockup_panic;
extern unsigned int hardlockup_panic;
void lockup_detector_init(void);
#else
+static inline void touch_softlockup_watchdog_sched(void)
+{
+}
static inline void touch_softlockup_watchdog(void)
{
}
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 0197358f1e81..0e32bc71245e 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -618,4 +618,10 @@ static inline int workqueue_sysfs_register(struct workqueue_struct *wq)
{ return 0; }
#endif /* CONFIG_SYSFS */
+#ifdef CONFIG_WQ_WATCHDOG
+void wq_watchdog_touch(int cpu);
+#else /* CONFIG_WQ_WATCHDOG */
+static inline void wq_watchdog_touch(int cpu) { }
+#endif /* CONFIG_WQ_WATCHDOG */
+
#endif
diff --git a/include/uapi/media/msm_jpeg_dma.h b/include/uapi/media/msm_jpeg_dma.h
index df3c7ee5b7cf..6b664566cb4c 100644
--- a/include/uapi/media/msm_jpeg_dma.h
+++ b/include/uapi/media/msm_jpeg_dma.h
@@ -17,6 +17,7 @@
/* msm jpeg dma control ID's */
#define V4L2_CID_JPEG_DMA_SPEED (V4L2_CID_PRIVATE_BASE)
+#define V4L2_CID_JPEG_DMA_MAX_DOWN_SCALE (V4L2_CID_PRIVATE_BASE + 1)
/* msm_jpeg_dma_buf */
struct msm_jpeg_dma_buff {
diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c
index caf4041f5b0a..bc54e84675da 100644
--- a/kernel/sched/clock.c
+++ b/kernel/sched/clock.c
@@ -354,7 +354,7 @@ void sched_clock_idle_wakeup_event(u64 delta_ns)
return;
sched_clock_tick();
- touch_softlockup_watchdog();
+ touch_softlockup_watchdog_sched();
}
EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event);
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 89dcc6cafa07..7f0f1d8d46b0 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -163,7 +163,7 @@ static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
* when we go busy again does not account too much ticks.
*/
if (ts->tick_stopped) {
- touch_softlockup_watchdog();
+ touch_softlockup_watchdog_sched();
if (is_idle_task(current))
ts->idle_jiffies++;
}
@@ -450,7 +450,7 @@ static void tick_nohz_update_jiffies(ktime_t now)
tick_do_update_jiffies64(now);
local_irq_restore(flags);
- touch_softlockup_watchdog();
+ touch_softlockup_watchdog_sched();
}
/*
@@ -721,7 +721,7 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
update_cpu_load_nohz();
calc_load_exit_idle();
- touch_softlockup_watchdog();
+ touch_softlockup_watchdog_sched();
/*
* Cancel the scheduled timer and restore the tick
*/
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index d12d5b86a555..b40f7f35413d 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -20,6 +20,7 @@
#include <linux/smpboot.h>
#include <linux/sched/rt.h>
#include <linux/tick.h>
+#include <linux/workqueue.h>
#include <asm/irq_regs.h>
#include <linux/kvm_para.h>
@@ -232,7 +233,15 @@ static void __touch_watchdog(void)
__this_cpu_write(watchdog_touch_ts, get_timestamp());
}
-void touch_softlockup_watchdog(void)
+/**
+ * touch_softlockup_watchdog_sched - touch watchdog on scheduler stalls
+ *
+ * Call when the scheduler may have stalled for legitimate reasons
+ * preventing the watchdog task from executing - e.g. the scheduler
+ * entering idle state. This should only be used for scheduler events.
+ * Use touch_softlockup_watchdog() for everything else.
+ */
+void touch_softlockup_watchdog_sched(void)
{
/*
* Preemption can be enabled. It doesn't matter which CPU's timestamp
@@ -240,6 +249,12 @@ void touch_softlockup_watchdog(void)
*/
raw_cpu_write(watchdog_touch_ts, 0);
}
+
+void touch_softlockup_watchdog(void)
+{
+ touch_softlockup_watchdog_sched();
+ wq_watchdog_touch(raw_smp_processor_id());
+}
EXPORT_SYMBOL(touch_softlockup_watchdog);
void touch_all_softlockup_watchdogs(void)
@@ -253,6 +268,7 @@ void touch_all_softlockup_watchdogs(void)
*/
for_each_watchdog_cpu(cpu)
per_cpu(watchdog_touch_ts, cpu) = 0;
+ wq_watchdog_touch(-1);
}
#ifdef CONFIG_HARDLOCKUP_DETECTOR
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 15dacf9590cb..58fe79122a61 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -149,6 +149,8 @@ struct worker_pool {
int id; /* I: pool ID */
unsigned int flags; /* X: flags */
+ unsigned long watchdog_ts; /* L: watchdog timestamp */
+
struct list_head worklist; /* L: list of pending works */
int nr_workers; /* L: total number of workers */
@@ -1084,6 +1086,8 @@ static void pwq_activate_delayed_work(struct work_struct *work)
struct pool_workqueue *pwq = get_work_pwq(work);
trace_workqueue_activate_work(work);
+ if (list_empty(&pwq->pool->worklist))
+ pwq->pool->watchdog_ts = jiffies;
move_linked_works(work, &pwq->pool->worklist, NULL);
__clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work));
pwq->nr_active++;
@@ -1386,6 +1390,8 @@ retry:
trace_workqueue_activate_work(work);
pwq->nr_active++;
worklist = &pwq->pool->worklist;
+ if (list_empty(worklist))
+ pwq->pool->watchdog_ts = jiffies;
} else {
work_flags |= WORK_STRUCT_DELAYED;
worklist = &pwq->delayed_works;
@@ -2159,6 +2165,8 @@ recheck:
list_first_entry(&pool->worklist,
struct work_struct, entry);
+ pool->watchdog_ts = jiffies;
+
if (likely(!(*work_data_bits(work) & WORK_STRUCT_LINKED))) {
/* optimization path, not strictly necessary */
process_one_work(worker, work);
@@ -2242,6 +2250,7 @@ repeat:
struct pool_workqueue, mayday_node);
struct worker_pool *pool = pwq->pool;
struct work_struct *work, *n;
+ bool first = true;
__set_current_state(TASK_RUNNING);
list_del_init(&pwq->mayday_node);
@@ -2258,9 +2267,14 @@ repeat:
* process'em.
*/
WARN_ON_ONCE(!list_empty(scheduled));
- list_for_each_entry_safe(work, n, &pool->worklist, entry)
- if (get_work_pwq(work) == pwq)
+ list_for_each_entry_safe(work, n, &pool->worklist, entry) {
+ if (get_work_pwq(work) == pwq) {
+ if (first)
+ pool->watchdog_ts = jiffies;
move_linked_works(work, scheduled, &n);
+ }
+ first = false;
+ }
if (!list_empty(scheduled)) {
process_scheduled_works(rescuer);
@@ -3071,6 +3085,7 @@ static int init_worker_pool(struct worker_pool *pool)
pool->cpu = -1;
pool->node = NUMA_NO_NODE;
pool->flags |= POOL_DISASSOCIATED;
+ pool->watchdog_ts = jiffies;
INIT_LIST_HEAD(&pool->worklist);
INIT_LIST_HEAD(&pool->idle_list);
hash_init(pool->busy_hash);
@@ -4310,7 +4325,9 @@ void show_workqueue_state(void)
pr_info("pool %d:", pool->id);
pr_cont_pool_info(pool);
- pr_cont(" workers=%d", pool->nr_workers);
+ pr_cont(" hung=%us workers=%d",
+ jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000,
+ pool->nr_workers);
if (pool->manager)
pr_cont(" manager: %d",
task_pid_nr(pool->manager->task));
@@ -5169,6 +5186,154 @@ static void workqueue_sysfs_unregister(struct workqueue_struct *wq)
static void workqueue_sysfs_unregister(struct workqueue_struct *wq) { }
#endif /* CONFIG_SYSFS */
+/*
+ * Workqueue watchdog.
+ *
+ * Stall may be caused by various bugs - missing WQ_MEM_RECLAIM, illegal
+ * flush dependency, a concurrency managed work item which stays RUNNING
+ * indefinitely. Workqueue stalls can be very difficult to debug as the
+ * usual warning mechanisms don't trigger and internal workqueue state is
+ * largely opaque.
+ *
+ * Workqueue watchdog monitors all worker pools periodically and dumps
+ * state if some pools failed to make forward progress for a while where
+ * forward progress is defined as the first item on ->worklist changing.
+ *
+ * This mechanism is controlled through the kernel parameter
+ * "workqueue.watchdog_thresh" which can be updated at runtime through the
+ * corresponding sysfs parameter file.
+ */
+#ifdef CONFIG_WQ_WATCHDOG
+
+static void wq_watchdog_timer_fn(unsigned long data);
+
+static unsigned long wq_watchdog_thresh = 30;
+static struct timer_list wq_watchdog_timer =
+ TIMER_DEFERRED_INITIALIZER(wq_watchdog_timer_fn, 0, 0);
+
+static unsigned long wq_watchdog_touched = INITIAL_JIFFIES;
+static DEFINE_PER_CPU(unsigned long, wq_watchdog_touched_cpu) = INITIAL_JIFFIES;
+
+static void wq_watchdog_reset_touched(void)
+{
+ int cpu;
+
+ wq_watchdog_touched = jiffies;
+ for_each_possible_cpu(cpu)
+ per_cpu(wq_watchdog_touched_cpu, cpu) = jiffies;
+}
+
+static void wq_watchdog_timer_fn(unsigned long data)
+{
+ unsigned long thresh = READ_ONCE(wq_watchdog_thresh) * HZ;
+ bool lockup_detected = false;
+ struct worker_pool *pool;
+ int pi;
+
+ if (!thresh)
+ return;
+
+ rcu_read_lock();
+
+ for_each_pool(pool, pi) {
+ unsigned long pool_ts, touched, ts;
+
+ if (list_empty(&pool->worklist))
+ continue;
+
+ /* get the latest of pool and touched timestamps */
+ pool_ts = READ_ONCE(pool->watchdog_ts);
+ touched = READ_ONCE(wq_watchdog_touched);
+
+ if (time_after(pool_ts, touched))
+ ts = pool_ts;
+ else
+ ts = touched;
+
+ if (pool->cpu >= 0) {
+ unsigned long cpu_touched =
+ READ_ONCE(per_cpu(wq_watchdog_touched_cpu,
+ pool->cpu));
+ if (time_after(cpu_touched, ts))
+ ts = cpu_touched;
+ }
+
+ /* did we stall? */
+ if (time_after(jiffies, ts + thresh)) {
+ lockup_detected = true;
+ pr_emerg("BUG: workqueue lockup - pool");
+ pr_cont_pool_info(pool);
+ pr_cont(" stuck for %us!\n",
+ jiffies_to_msecs(jiffies - pool_ts) / 1000);
+ }
+ }
+
+ rcu_read_unlock();
+
+ if (lockup_detected)
+ show_workqueue_state();
+
+ wq_watchdog_reset_touched();
+ mod_timer(&wq_watchdog_timer, jiffies + thresh);
+}
+
+void wq_watchdog_touch(int cpu)
+{
+ if (cpu >= 0)
+ per_cpu(wq_watchdog_touched_cpu, cpu) = jiffies;
+ else
+ wq_watchdog_touched = jiffies;
+}
+
+static void wq_watchdog_set_thresh(unsigned long thresh)
+{
+ wq_watchdog_thresh = 0;
+ del_timer_sync(&wq_watchdog_timer);
+
+ if (thresh) {
+ wq_watchdog_thresh = thresh;
+ wq_watchdog_reset_touched();
+ mod_timer(&wq_watchdog_timer, jiffies + thresh * HZ);
+ }
+}
+
+static int wq_watchdog_param_set_thresh(const char *val,
+ const struct kernel_param *kp)
+{
+ unsigned long thresh;
+ int ret;
+
+ ret = kstrtoul(val, 0, &thresh);
+ if (ret)
+ return ret;
+
+ if (system_wq)
+ wq_watchdog_set_thresh(thresh);
+ else
+ wq_watchdog_thresh = thresh;
+
+ return 0;
+}
+
+static const struct kernel_param_ops wq_watchdog_thresh_ops = {
+ .set = wq_watchdog_param_set_thresh,
+ .get = param_get_ulong,
+};
+
+module_param_cb(watchdog_thresh, &wq_watchdog_thresh_ops, &wq_watchdog_thresh,
+ 0644);
+
+static void wq_watchdog_init(void)
+{
+ wq_watchdog_set_thresh(wq_watchdog_thresh);
+}
+
+#else /* CONFIG_WQ_WATCHDOG */
+
+static inline void wq_watchdog_init(void) { }
+
+#endif /* CONFIG_WQ_WATCHDOG */
+
static void __init wq_numa_init(void)
{
cpumask_var_t *tbl;
@@ -5292,6 +5457,9 @@ static int __init init_workqueues(void)
!system_unbound_wq || !system_freezable_wq ||
!system_power_efficient_wq ||
!system_freezable_power_efficient_wq);
+
+ wq_watchdog_init();
+
return 0;
}
early_initcall(init_workqueues);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 9e27a3c3aeb4..36ea0d54e05b 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -255,6 +255,13 @@ config PAGE_OWNER
If unsure, say N.
+config PAGE_OWNER_ENABLE_DEFAULT
+ bool "Enable Track page owner by default"
+ depends on PAGE_OWNER
+ ---help---
+ Enable track page owner by default? This value
+ can be overridden by page_owner_disabled=off|on.
+
config DEBUG_FS
bool "Debug Filesystem"
help
@@ -824,6 +831,17 @@ config BOOTPARAM_HUNG_TASK_PANIC_VALUE
default 0 if !BOOTPARAM_HUNG_TASK_PANIC
default 1 if BOOTPARAM_HUNG_TASK_PANIC
+config WQ_WATCHDOG
+ bool "Detect Workqueue Stalls"
+ depends on DEBUG_KERNEL
+ help
+ Say Y here to enable stall detection on workqueues. If a
+ worker pool doesn't make forward progress on a pending work
+ item for over a given amount of time, 30s by default, a
+ warning message is printed along with dump of workqueue
+ state. This can be configured through kernel parameter
+ "workqueue.watchdog_thresh" and its sysfs counterpart.
+
endmenu # "Debug lockups and hangs"
config PANIC_ON_OOPS
@@ -1934,6 +1952,19 @@ config MEMTEST
memtest=17, mean do 17 test patterns.
If you are unsure how to answer this question, answer N.
+config MEMTEST_ENABLE_DEFAULT
+ int "Enable Memtest pattern test by default? (0-17)"
+ range 0 17
+ default "0"
+ depends on MEMTEST
+ help
+ This option helps to select Memtest to be enabled through
+ kernel defconfig options. Alternatively it can be enabled
+ using memtest=<patterns> kernel command line.
+
+ Default value is kept as "0" so that it is kept as disabled.
+ To enable enter any value between 1-17 range.
+
config TEST_STATIC_KEYS
tristate "Test static keys"
default n
diff --git a/lib/Makefile b/lib/Makefile
index 79599c7b9828..03a447a234cc 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -22,8 +22,7 @@ lib-$(CONFIG_SMP) += cpumask.o
lib-y += kobject.o klist.o
obj-y += lockref.o
-KASAN_SANITIZE_find_next_bit.o := n
-KASAN_SANITIZE_find_last_bit.o := n
+KASAN_SANITIZE_find_bit.o := n
obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
diff --git a/mm/memtest.c b/mm/memtest.c
index 8eaa4c3a5f65..15a423eb0c29 100644
--- a/mm/memtest.c
+++ b/mm/memtest.c
@@ -80,8 +80,8 @@ static void __init do_one_pass(u64 pattern, phys_addr_t start, phys_addr_t end)
}
/* default is disabled */
-static unsigned int memtest_pattern __initdata;
-
+static unsigned int memtest_pattern __initdata =
+ CONFIG_MEMTEST_ENABLE_DEFAULT;
static int __init parse_memtest(char *arg)
{
int ret = 0;
diff --git a/mm/page_owner.c b/mm/page_owner.c
index 983c3a10fa07..45cccaa1ce32 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -7,7 +7,8 @@
#include <linux/page_owner.h>
#include "internal.h"
-static bool page_owner_disabled = true;
+static bool page_owner_disabled =
+ !IS_ENABLED(CONFIG_PAGE_OWNER_ENABLE_DEFAULT);
bool page_owner_inited __read_mostly;
static void init_early_allocated_pages(void);
@@ -20,6 +21,9 @@ static int early_page_owner_param(char *buf)
if (strcmp(buf, "on") == 0)
page_owner_disabled = false;
+ if (strcmp(buf, "off") == 0)
+ page_owner_disabled = true;
+
return 0;
}
early_param("page_owner", early_page_owner_param);
diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c
index 4f1ce53f7efa..ee4a8733b3e1 100644
--- a/net/ipc_router/ipc_router_core.c
+++ b/net/ipc_router/ipc_router_core.c
@@ -198,6 +198,8 @@ static int process_resume_tx_msg(union rr_control_msg *msg,
static void ipc_router_reset_conn(struct msm_ipc_router_remote_port *rport_ptr);
static int ipc_router_get_xprt_info_ref(
struct msm_ipc_router_xprt_info *xprt_info);
+static void ipc_router_put_xprt_info_ref(
+ struct msm_ipc_router_xprt_info *xprt_info);
static void ipc_router_release_xprt_info_ref(struct kref *ref);
struct pil_vote_info {
@@ -2081,7 +2083,7 @@ static int forward_msg(struct msm_ipc_router_xprt_info *xprt_info,
fm_error3:
mutex_unlock(&fwd_xprt_info->tx_lock_lhb2);
fm_error2:
- kref_put(&fwd_xprt_info->ref, ipc_router_release_xprt_info_ref);
+ ipc_router_put_xprt_info_ref(fwd_xprt_info);
fm_error_xprt:
up_read(&rt_entry->lock_lha4);
fm_error1:
@@ -3084,7 +3086,7 @@ out_write_pkt:
ipc_router_log_msg(xprt_info->log_ctx,
IPC_ROUTER_LOG_EVENT_TX_ERR, pkt, hdr, src, rport_ptr);
- kref_put(&xprt_info->ref, ipc_router_release_xprt_info_ref);
+ ipc_router_put_xprt_info_ref(xprt_info);
return ret;
}
update_comm_mode_info(&src->mode_info, xprt_info);
@@ -3102,7 +3104,7 @@ out_write_pkt:
(hdr->size & 0xffff));
}
- kref_put(&xprt_info->ref, ipc_router_release_xprt_info_ref);
+ ipc_router_put_xprt_info_ref(xprt_info);
return hdr->size;
}
@@ -3254,8 +3256,8 @@ static int msm_ipc_router_send_resume_tx(void *data)
}
ret = ipc_router_send_ctl_msg(rt_entry->xprt_info, &msg,
hdr->src_node_id);
+ ipc_router_put_xprt_info_ref(rt_entry->xprt_info);
kref_put(&rt_entry->ref, ipc_router_release_rtentry);
- kref_put(&rt_entry->xprt_info->ref, ipc_router_release_xprt_info_ref);
if (ret < 0)
IPC_RTR_ERR(
"%s: Send Resume_Tx Failed SRC_NODE: %d SRC_PORT: %d DEST_NODE: %d",
@@ -3982,6 +3984,9 @@ static int ipc_router_get_xprt_info_ref(
int ret = -ENODEV;
struct msm_ipc_router_xprt_info *tmp_xprt_info;
+ if (!xprt_info)
+ return 0;
+
down_read(&xprt_info_list_lock_lha5);
list_for_each_entry(tmp_xprt_info, &xprt_info_list, list) {
if (tmp_xprt_info == xprt_info) {
@@ -3996,6 +4001,20 @@ static int ipc_router_get_xprt_info_ref(
}
/**
+ * ipc_router_put_xprt_info_ref() - Put a reference to the xprt_info structure
+ * @xprt_info: pointer to the xprt_info.
+ *
+ * This function is used to put the reference to the xprt_info structure
+ * corresponding to the requested @xprt_info pointer.
+ */
+static void ipc_router_put_xprt_info_ref(
+ struct msm_ipc_router_xprt_info *xprt_info)
+{
+ if (xprt_info)
+ kref_put(&xprt_info->ref, ipc_router_release_xprt_info_ref);
+}
+
+/**
* ipc_router_release_xprt_info_ref() - release the xprt_info last reference
* @ref: Reference to the xprt_info structure.
*
@@ -4095,8 +4114,7 @@ static void msm_ipc_router_remove_xprt(struct msm_ipc_router_xprt *xprt)
wakeup_source_trash(&xprt_info->ws);
- kref_put(&xprt_info->ref,
- ipc_router_release_xprt_info_ref);
+ ipc_router_put_xprt_info_ref(xprt_info);
wait_for_completion(&xprt_info->ref_complete);
xprt->priv = 0;
diff --git a/security/pfe/pfk_ice.c b/security/pfe/pfk_ice.c
index 9d4961aa8330..2f09d8801a96 100644
--- a/security/pfe/pfk_ice.c
+++ b/security/pfe/pfk_ice.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -103,8 +103,16 @@ int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt)
desc.args[3] = virt_to_phys(tzbuf_salt);
desc.args[4] = tzbuflen_salt;
+ ret = qcom_ice_setup_ice_hw("ufs", true);
+ if (ret) {
+ pr_err("%s: could not enable clocks: 0x%x\n", __func__, ret);
+ return ret;
+ }
+
+ ret = scm_call2(smc_id, &desc);
+
+ qcom_ice_setup_ice_hw("ufs", false);
- ret = scm_call2_atomic(smc_id, &desc);
pr_debug(" %s , ret = %d\n", __func__, ret);
if (ret) {
pr_err("%s: Error: 0x%x\n", __func__, ret);
@@ -112,7 +120,7 @@ int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt)
smc_id = TZ_ES_INVALIDATE_ICE_KEY_ID;
desc.arginfo = TZ_ES_INVALIDATE_ICE_KEY_PARAM_ID;
desc.args[0] = index;
- scm_call2_atomic(smc_id, &desc);
+ scm_call2(smc_id, &desc);
}
return ret;
@@ -136,10 +144,12 @@ int qti_pfk_ice_invalidate_key(uint32_t index)
desc.args[0] = index;
ret = qcom_ice_setup_ice_hw("ufs", true);
- if (ret)
+ if (ret) {
pr_err("%s: could not enable clocks: 0x%x\n", __func__, ret);
+ return ret;
+ }
- ret = scm_call2_atomic(smc_id, &desc);
+ ret = scm_call2(smc_id, &desc);
qcom_ice_setup_ice_hw("ufs", false);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index dad53baec605..23261271bec8 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1322,6 +1322,12 @@ int q6asm_audio_client_buf_alloc_contiguous(unsigned int dir,
ac->port[dir].buf = buf;
+ /* check for integer overflow */
+ if ((bufcnt > 0) && ((INT_MAX / bufcnt) < bufsz)) {
+ pr_err("%s: integer overflow\n", __func__);
+ mutex_unlock(&ac->cmd_lock);
+ goto fail;
+ }
bytes_to_alloc = bufsz * bufcnt;
/* The size to allocate should be multiple of 4K bytes */