Merge "wil6210: add oob_mode for AP certification" into msm-4.9
diff --git a/Documentation/devicetree/bindings/display/msm/sde.txt b/Documentation/devicetree/bindings/display/msm/sde.txt
index bc226a7..a3ef34c 100644
--- a/Documentation/devicetree/bindings/display/msm/sde.txt
+++ b/Documentation/devicetree/bindings/display/msm/sde.txt
@@ -128,6 +128,8 @@
feature is available or not.
- qcom,sde-has-dim-layer: Boolean property to indicate if mixer has dim layer
feature is available or not.
+- qcom,sde-has-idle-pc: Boolean property to indicate if target has idle
+ power collapse feature available or not.
- qcom,sde-has-mixer-gc: Boolean property to indicate if mixer has gamma correction
feature available or not.
- qcom,sde-has-cdp: Boolean property to indicate if cdp feature is
@@ -420,6 +422,7 @@
qcom,sde-csc-type = "csc-10bit";
qcom,sde-highest-bank-bit = <15>;
qcom,sde-has-mixer-gc;
+ qcom,sde-has-idle-pc;
qcom,sde-sspp-max-rects = <1 1 1 1
1 1 1 1
1 1
diff --git a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
index 3e7fcb7..ffba081 100644
--- a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
@@ -35,7 +35,7 @@
- qcom,mdss-dsi-panel-destination: A string that specifies the destination display for the panel.
"display_1" = DISPLAY_1
"display_2" = DISPLAY_2
-- qcom,mdss-dsi-panel-timings: An array of length 12 that specifies the PHY
+- qcom,mdss-dsi-panel-phy-timings: An array of length 12 that specifies the PHY
timing settings for the panel.
- qcom,mdss-dsi-panel-timings-8996: An array of length 40 char that specifies the 8996 PHY lane
timing settings for the panel.
@@ -456,28 +456,6 @@
with the supply entry index. For a detailed description of
fields in the supply entry, refer to the qcom,ctrl-supply-entries
binding above.
-- qcom,config-select: Optional property to select default configuration.
-
-[[Optional config sub-nodes]] These subnodes provide different configurations for a given same panel.
- Default configuration can be chosen by specifying phandle of the
- selected subnode in the qcom,config-select.
-Required properties for sub-nodes: None
-Optional properites:
-- qcom,lm-split: An array of two values indicating MDP should use two layer
- mixers to reduce power.
- Ex: Normally 1080x1920 display uses single DSI and thus one layer
- mixer. But if we use two layer mixers then mux the output of
- those two mixers into single stream and route it to single DSI
- then we can lower the clock requirements of MDP. To use this
- configuration we need two fill this array with <540 540>.
- Both values doesn't have to be same, but recommended, however sum of
- both values has to be equal to the panel-width.
- By default two mixer streams are merged using 2D mux, however if
- 2 DSC encoders are used then merge is performed within compression
- engine.
-- qcom,split-mode: String property indicating which split mode MDP should use. Valid
- entries are "pingpong-split" and "dualctl-split".
- This property is mutually exclusive with qcom,lm-split.
- qcom,mdss-dsc-version: An 8 bit value indicates the DSC version supported by panel. Bits[0.3]
provides information about minor version while Bits[4.7] provides
major version information. It supports only DSC rev 1(Major).1(Minor)
@@ -500,6 +478,21 @@
- qcom,mdss-dsc-block-prediction-enable: A boolean value to enable/disable the block prediction at decoder.
- qcom,mdss-dsc-config-by-manufacture-cmd: A boolean to indicates panel use manufacture command to setup pps
instead of standard dcs type 0x0A.
+- qcom,display-topology: Array of u32 values which specifies the list of topologies available
+ for the display. A display topology is defined by a
+ set of 3 values in the order:
+ - number of mixers
+ - number of compression encoders
+ - number of interfaces
+ Therefore, the array should always contain a tuple of 3 elements.
+- qcom,default-topology-index: An u32 value which indexes the topology set
+ specified by the node "qcom,display-topology"
+ to identify the default topology for the
+ display. The first set is indexed by the
+ value 0.
+
+Required properties for sub-nodes: None
+Optional properties:
- qcom,dba-panel: Indicates whether the current panel is used as a display bridge
to a non-DSI interface.
- qcom,bridge-name: A string to indicate the name of the bridge chip connected to DSI. qcom,bridge-name
@@ -692,18 +685,15 @@
29 00 00 00 00 00 02 F1 00];
qcom,mdss-dsi-timing-switch-command-state = "dsi_lp_mode";
- qcom,config-select = <&dsi_sim_vid_config0>;
- dsi_sim_vid_config0: config0 {
- qcom,lm-split = <360 360>;
- qcom,mdss-dsc-encoders = <2>;
- qcom,mdss-dsc-slice-height = <16>;
- qcom,mdss-dsc-slice-width = <360>;
- qcom,mdss-dsc-slice-per-pkt = <2>;
- qcom,mdss-dsc-bit-per-component = <8>;
- qcom,mdss-dsc-bit-per-pixel = <8>;
- qcom,mdss-dsc-block-prediction-enable;
- qcom,mdss-dsc-config-by-manufacture-cmd;
- };
+ qcom,mdss-dsc-slice-height = <16>;
+ qcom,mdss-dsc-slice-width = <360>;
+ qcom,mdss-dsc-slice-per-pkt = <2>;
+ qcom,mdss-dsc-bit-per-component = <8>;
+ qcom,mdss-dsc-bit-per-pixel = <8>;
+ qcom,mdss-dsc-block-prediction-enable;
+ qcom,mdss-dsc-config-by-manufacture-cmd;
+ qcom,display-topology = <1 1 1>;
+ qcom,default-topology-index = <0>;
};
};
qcom,panel-supply-entries {
@@ -737,41 +727,19 @@
};
};
- qcom,config-select = <&dsi_sim_vid_config0>;
qcom,dba-panel;
qcom,bridge-name = "adv7533";
qcom,mdss-dsc-version = <0x11>;
qcom,mdss-dsc-scr-version = <0x1>;
-
- dsi_sim_vid_config0: config0 {
- qcom,lm-split = <360 360>;
- qcom,mdss-dsc-encoders = <2>;
- qcom,mdss-dsc-slice-height = <16>;
- qcom,mdss-dsc-slice-width = <360>;
- qcom,mdss-dsc-slice-per-pkt = <2>;
- qcom,mdss-dsc-bit-per-component = <8>;
- qcom,mdss-dsc-bit-per-pixel = <8>;
- qcom,mdss-dsc-block-prediction-enable;
- qcom,mdss-dsc-config-by-manufacture-cmd;
- };
-
- dsi_sim_vid_config1: config1 {
- qcom,mdss-dsc-encoders = <1>;
- qcom,mdss-dsc-slice-height = <16>;
- qcom,mdss-dsc-slice-width = <360>;
- qcom,mdss-dsc-slice-per-pkt = <2>;
- qcom,mdss-dsc-bit-per-component = <8>;
- qcom,mdss-dsc-bit-per-pixel = <8>;
- qcom,mdss-dsc-block-prediction-enable;
- qcom,mdss-dsc-config-by-manufacture-cmd;
- };
-
- dsi_sim_vid_config2: config2 {
- qcom,split-mode = "dualctl-split";
- };
-
- dsi_sim_vid_config3: config3 {
- qcom,split-mode = "pingpong-split";
- };
+ qcom,mdss-dsc-slice-height = <16>;
+ qcom,mdss-dsc-slice-width = <360>;
+ qcom,mdss-dsc-slice-per-pkt = <2>;
+ qcom,mdss-dsc-bit-per-component = <8>;
+ qcom,mdss-dsc-bit-per-pixel = <8>;
+ qcom,mdss-dsc-block-prediction-enable;
+ qcom,mdss-dsc-config-by-manufacture-cmd;
+ qcom,display-topology = <1 1 1>,
+ <2 2 1>;
+ qcom,default-topology-index = <0>;
};
};
diff --git a/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt b/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
index 04b624b..0173a3d 100644
--- a/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
+++ b/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
@@ -19,6 +19,7 @@
Optional properties:
- qcom,bus-mas: contains the bus master id needed to put in bus bandwidth votes
for inter-connect buses.
+- qcom,wakeup-byte: Byte to be injected in the tty layer during wakeup isr.
Example:
qupv3_uart11: qcom,qup_uart@0xa88000 {
@@ -34,4 +35,5 @@
pinctrl-1 = <&qup_1_uart_3_sleep>;
interrupts = <0 355 0>;
qcom,bus-mas = <MASTER_BLSP_2>;
+ qcom,wakeup-byte = <0xFF>;
};
diff --git a/Makefile b/Makefile
index 2b8f550..06a55b5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 9
-SUBLEVEL = 25
+SUBLEVEL = 26
EXTRAVERSION =
NAME = Roaring Lionus
diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h
index b65930a..54b54da 100644
--- a/arch/arc/include/asm/atomic.h
+++ b/arch/arc/include/asm/atomic.h
@@ -17,10 +17,11 @@
#include <asm/barrier.h>
#include <asm/smp.h>
+#define ATOMIC_INIT(i) { (i) }
+
#ifndef CONFIG_ARC_PLAT_EZNPS
#define atomic_read(v) READ_ONCE((v)->counter)
-#define ATOMIC_INIT(i) { (i) }
#ifdef CONFIG_ARC_HAS_LLSC
diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h
index b5ff87e..aee1a77 100644
--- a/arch/arc/include/asm/entry-arcv2.h
+++ b/arch/arc/include/asm/entry-arcv2.h
@@ -16,6 +16,7 @@
;
; Now manually save: r12, sp, fp, gp, r25
+ PUSH r30
PUSH r12
; Saving pt_regs->sp correctly requires some extra work due to the way
@@ -72,6 +73,7 @@
POPAX AUX_USER_SP
1:
POP r12
+ POP r30
.endm
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 69095da..47111d5 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -84,7 +84,7 @@
unsigned long fp;
unsigned long sp; /* user/kernel sp depending on where we came from */
- unsigned long r12;
+ unsigned long r12, r30;
/*------- Below list auto saved by h/w -----------*/
unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
index 16d2474..6a3e8b4 100644
--- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
@@ -145,7 +145,6 @@
<0 1000>;
anoc_1_tbu: anoc_1_tbu@0x150c5000 {
- status = "disabled";
compatible = "qcom,qsmmuv500-tbu";
reg = <0x150c5000 0x1000>,
<0x150c2200 0x8>;
@@ -167,7 +166,6 @@
};
anoc_2_tbu: anoc_2_tbu@0x150c9000 {
- status = "disabled";
compatible = "qcom,qsmmuv500-tbu";
reg = <0x150c9000 0x1000>,
<0x150c2208 0x8>;
@@ -189,7 +187,6 @@
};
mnoc_hf_0_tbu: mnoc_hf_0_tbu@0x150cd000 {
- status = "disabled";
compatible = "qcom,qsmmuv500-tbu";
reg = <0x150cd000 0x1000>,
<0x150c2210 0x8>;
@@ -211,7 +208,6 @@
};
mnoc_hf_1_tbu: mnoc_hf_1_tbu@0x150d1000 {
- status = "disabled";
compatible = "qcom,qsmmuv500-tbu";
reg = <0x150d1000 0x1000>,
<0x150c2218 0x8>;
@@ -233,7 +229,6 @@
};
mnoc_sf_0_tbu: mnoc_sf_0_tbu@0x150d5000 {
- status = "disabled";
compatible = "qcom,qsmmuv500-tbu";
reg = <0x150d5000 0x1000>,
<0x150c2220 0x8>;
@@ -255,7 +250,6 @@
};
compute_dsp_tbu: compute_dsp_tbu@0x150d9000 {
- status = "disabled";
compatible = "qcom,qsmmuv500-tbu";
reg = <0x150d9000 0x1000>,
<0x150c2228 0x8>;
@@ -276,7 +270,6 @@
};
adsp_tbu: adsp_tbu@0x150dd000 {
- status = "disabled";
compatible = "qcom,qsmmuv500-tbu";
reg = <0x150dd000 0x1000>,
<0x150c2230 0x8>;
@@ -298,7 +291,6 @@
};
anoc_1_pcie_tbu: anoc_1_pcie_tbu@0x150e1000 {
- status = "disabled";
compatible = "qcom,qsmmuv500-tbu";
reg = <0x150e1000 0x1000>,
<0x150c2238 0x8>;
@@ -336,9 +328,9 @@
apps_iommu_test_device {
compatible = "iommu-debug-test";
/*
- * This SID belongs to PCIE. We can't use a fake SID for
+ * This SID belongs to QUP1-GSI. We can't use a fake SID for
* the apps_smmu device.
*/
- iommus = <&apps_smmu 0x1c03 0>;
+ iommus = <&apps_smmu 0x16 0>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi
index b119305..b9a6c79 100644
--- a/arch/arm64/boot/dts/qcom/pm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi
@@ -67,6 +67,8 @@
reg = <0x2400 0x100>;
interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>;
label = "pm8998_tz";
+ qcom,channel-num = <6>;
+ qcom,temp_alarm-vadc = <&pm8998_vadc>;
#thermal-sensor-cells = <0>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts
index d5646bf..6569219 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-cdp.dts
@@ -21,3 +21,26 @@
compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
qcom,board-id = <1 1>;
};
+
+&dsi_dual_nt35597_truly_video_display {
+ /delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+ connectors = <&sde_wb &dsi_sharp_4k_dsc_video_display>;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-panel-mode-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+ qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts
index d641276..2e893de 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-4k-panel-mtp.dts
@@ -21,3 +21,26 @@
compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
qcom,board-id = <8 1>;
};
+
+&dsi_dual_nt35597_truly_video_display {
+ /delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+ connectors = <&sde_wb &dsi_sharp_4k_dsc_video_display>;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-panel-mode-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+ qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
index c0189a4..922e990 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
@@ -118,10 +118,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_rear_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -157,10 +159,12 @@
cam_vdig-supply = <&camera_ldo>;
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
- qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
- qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
- qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
- qcom,cam-vreg-op-mode = <105000 0 80000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000 0>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000 0>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -193,10 +197,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_active
@@ -240,10 +246,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_rear_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -280,10 +288,12 @@
cam_vdig-supply = <&camera_ldo>;
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
- qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
- qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
- qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
- qcom,cam-vreg-op-mode = <105000 0 80000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000 0>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000 0>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -322,10 +332,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_active
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
index c0189a4..922e990 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
@@ -118,10 +118,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_rear_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -157,10 +159,12 @@
cam_vdig-supply = <&camera_ldo>;
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
- qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
- qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
- qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
- qcom,cam-vreg-op-mode = <105000 0 80000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000 0>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000 0>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -193,10 +197,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_active
@@ -240,10 +246,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_rear_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -280,10 +288,12 @@
cam_vdig-supply = <&camera_ldo>;
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
- qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
- qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
- qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
- qcom,cam-vreg-op-mode = <105000 0 80000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000 0>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000 0>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -322,10 +332,12 @@
cam_vio-supply = <&pm8998_lvs1>;
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_ldo>;
- qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
- qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
- qcom,cam-vreg-op-mode = <0 80000 105000>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000 0>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000 0>;
+ qcom,cam-vreg-op-mode = <0 80000 105000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_active
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
index cd9c8a8..3b9c26f 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
@@ -71,7 +71,7 @@
<&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>,
<&clock_camcc CAM_CC_CSIPHY1_CLK>,
<&clock_camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>,
- <&clock_camcc CAM_CC_CSI0PHYTIMER_CLK>,
+ <&clock_camcc CAM_CC_CSI1PHYTIMER_CLK>,
<&clock_camcc CAM_CC_IFE_1_CSID_CLK>,
<&clock_camcc CAM_CC_IFE_1_CSID_CLK_SRC>;
clock-names = "camnoc_axi_clk",
@@ -225,4 +225,108 @@
status = "ok";
};
};
+
+ qcom,cam_smmu {
+ compatible = "qcom,msm-cam-smmu";
+ status = "ok";
+
+ msm_cam_smmu_ife {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&apps_smmu 0x808>,
+ <&apps_smmu 0x810>,
+ <&apps_smmu 0x818>,
+ <&apps_smmu 0xc08>,
+ <&apps_smmu 0xc10>,
+ <&apps_smmu 0xc18>;
+ label = "ife";
+ ife_iova_mem_map: iova-mem-map {
+ /* IO region is approximately 3.4 GB */
+ iova-mem-region-io {
+ iova-region-name = "io";
+ iova-region-start = <0x7400000>;
+ iova-region-len = <0xd8c00000>;
+ iova-region-id = <0x3>;
+ status = "ok";
+ };
+ };
+ };
+
+ msm_cam_icp_fw {
+ compatible = "qcom,msm-cam-smmu-fw-dev";
+ label="icp";
+ memory-region = <&pil_camera_mem>;
+ };
+
+ msm_cam_smmu_icp {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&apps_smmu 0x1078>,
+ <&apps_smmu 0x1020>,
+ <&apps_smmu 0x1028>,
+ <&apps_smmu 0x1040>,
+ <&apps_smmu 0x1048>,
+ <&apps_smmu 0x1030>,
+ <&apps_smmu 0x1050>;
+ label = "icp";
+ icp_iova_mem_map: iova-mem-map {
+ iova-mem-region-firmware {
+ /* Firmware region is 5MB */
+ iova-region-name = "firmware";
+ iova-region-start = <0x0>;
+ iova-region-len = <0x500000>;
+ iova-region-id = <0x0>;
+ status = "ok";
+ };
+
+ iova-mem-region-shared {
+ /* Shared region is 100MB long */
+ iova-region-name = "shared";
+ iova-region-start = <0x7400000>;
+ iova-region-len = <0x6400000>;
+ iova-region-id = <0x1>;
+ status = "ok";
+ };
+
+ iova-mem-region-io {
+ /* IO region is approximately 3.3 GB */
+ iova-region-name = "io";
+ iova-region-start = <0xd800000>;
+ iova-region-len = <0xd2800000>;
+ iova-region-id = <0x3>;
+ status = "ok";
+ };
+ };
+ };
+
+ msm_cam_smmu_cpas_cdm {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&apps_smmu 0x1000>;
+ label = "cpas-cdm0";
+ cpas_cdm_iova_mem_map: iova-mem-map {
+ iova-mem-region-io {
+ /* IO region is approximately 3.4 GB */
+ iova-region-name = "io";
+ iova-region-start = <0x7400000>;
+ iova-region-len = <0xd8c00000>;
+ iova-region-id = <0x3>;
+ status = "ok";
+ };
+ };
+ };
+
+ msm_cam_smmu_secure {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&apps_smmu 0x1001>;
+ label = "cam-secure";
+ cam_secure_iova_mem_map: iova-mem-map {
+ /* Secure IO region is approximately 3.4 GB */
+ iova-mem-region-io {
+ iova-region-name = "io";
+ iova-region-start = <0x7400000>;
+ iova-region-len = <0xd8c00000>;
+ iova-region-id = <0x3>;
+ status = "ok";
+ };
+ };
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index 6f40fae..af28003 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -206,6 +206,7 @@
spi0 = &qupv3_se8_spi;
i2c0 = &qupv3_se10_i2c;
i2c1 = &qupv3_se3_i2c;
+ hsuart0 = &qupv3_se6_4uart;
};
};
@@ -249,6 +250,10 @@
status = "ok";
};
+&qupv3_se6_4uart {
+ status = "ok";
+};
+
&usb1 {
status = "okay";
extcon = <&extcon_usb1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
index 91946d7..d1712ad 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
@@ -483,6 +483,16 @@
};
port@1 {
+ reg = <0>;
+ funnel_in2_in_modem_etm0: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&modem_etm0_out_funnel_in2>;
+ };
+
+ };
+
+ port@2 {
reg = <1>;
funnel_in2_in_replicator_swao: endpoint {
slave-mode;
@@ -492,7 +502,7 @@
};
- port@2 {
+ port@3 {
reg = <2>;
funnel_in2_in_funnel_modem: endpoint {
slave-mode;
@@ -502,7 +512,7 @@
};
- port@3 {
+ port@4 {
reg = <5>;
funnel_in2_in_funnel_apss_merg: endpoint {
slave-mode;
@@ -1746,6 +1756,20 @@
};
};
+ modem_etm0 {
+ compatible = "qcom,coresight-remote-etm";
+
+ coresight-name = "coresight-modem-etm0";
+ qcom,inst-id = <2>;
+
+ port {
+ modem_etm0_out_funnel_in2: endpoint {
+ remote-endpoint =
+ <&funnel_in2_in_modem_etm0>;
+ };
+ };
+ };
+
funnel_apss_merg: funnel@7810000 {
compatible = "arm,primecell";
arm,primecell-periphid = <0x0003b908>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
index 5e21756..77edb85 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
@@ -12,6 +12,12 @@
&soc {
+ pil_gpu: qcom,kgsl-hyp {
+ compatible = "qcom,pil-tz-generic";
+ qcom,pas-id = <13>;
+ qcom,firmware-name = "a630_zap";
+ };
+
msm_bus: qcom,kgsl-busmon{
label = "kgsl-busmon";
compatible = "qcom,kgsl-busmon";
@@ -77,13 +83,16 @@
#cooling-cells = <2>;
clocks = <&clock_gfx GPU_CC_GX_GFX3D_CLK>,
- <&clock_gcc GCC_GPU_CFG_AHB_CLK>,
<&clock_gpucc GPU_CC_CXO_CLK>,
<&clock_gcc GCC_DDRSS_GPU_AXI_CLK>,
- <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>;
+ <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>,
+ <&clock_gpucc GPU_CC_CX_GMU_CLK>,
+ <&clock_gpucc GPU_CC_AHB_CLK>,
+ <&clock_gpucc GPU_CC_GX_CXO_CLK>;
- clock-names = "core_clk", "iface_clk", "rbbmtimer_clk",
- "mem_clk", "mem_iface_clk";
+ clock-names = "core_clk", "rbbmtimer_clk", "mem_clk",
+ "mem_iface_clk", "gmu_clk", "ahb_clk",
+ "cxo_clk";
qcom,isense-clk-on-level = <1>;
@@ -162,19 +171,19 @@
qcom,gpu-pwrlevel@0 {
reg = <0>;
- qcom,gpu-freq = <548000000>;
- qcom,bus-freq = <12>;
- qcom,bus-min = <11>;
- qcom,bus-max = <12>;
+ qcom,gpu-freq = <280000000>;
+ qcom,bus-freq = <4>;
+ qcom,bus-min = <3>;
+ qcom,bus-max = <5>;
};
qcom,gpu-pwrlevel@1 {
reg = <1>;
- qcom,gpu-freq = <425000000>;
- qcom,bus-freq = <7>;
- qcom,bus-min = <6>;
- qcom,bus-max = <8>;
+ qcom,gpu-freq = <280000000>;
+ qcom,bus-freq = <4>;
+ qcom,bus-min = <3>;
+ qcom,bus-max = <5>;
};
qcom,gpu-pwrlevel@2 {
@@ -187,10 +196,10 @@
qcom,gpu-pwrlevel@3 {
reg = <3>;
- qcom,gpu-freq = <27000000>;
- qcom,bus-freq = <0>;
- qcom,bus-min = <0>;
- qcom,bus-max = <0>;
+ qcom,gpu-freq = <280000000>;
+ qcom,bus-freq = <4>;
+ qcom,bus-min = <3>;
+ qcom,bus-max = <5>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index 803843c..715b566 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -209,6 +209,7 @@
spi0 = &qupv3_se8_spi;
i2c0 = &qupv3_se10_i2c;
i2c1 = &qupv3_se3_i2c;
+ hsuart0 = &qupv3_se6_4uart;
};
};
@@ -228,6 +229,10 @@
status = "ok";
};
+&qupv3_se6_4uart {
+ status = "ok";
+};
+
&usb1 {
status = "okay";
extcon = <&extcon_usb1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pcie.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pcie.dtsi
new file mode 100644
index 0000000..da5d6fa
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-pcie.dtsi
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 <dt-bindings/clock/qcom,gcc-sdm845.h>
+
+&soc {
+ pcie0: qcom,pcie@0x1c00000 {
+ compatible = "qcom,pci-msm";
+ cell-index = <0>;
+
+ reg = <0x1c00000 0x2000>,
+ <0x1c06000 0x1000>,
+ <0x60000000 0xf1d>,
+ <0x60000f20 0xa8>,
+ <0x60100000 0x100000>,
+ <0x60200000 0x100000>,
+ <0x60300000 0xd00000>;
+
+ reg-names = "parf", "phy", "dm_core", "elbi",
+ "conf", "io", "bars";
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x01000000 0x0 0x60200000 0x60200000 0x0 0x100000>,
+ <0x02000000 0x0 0x60300000 0x60300000 0x0 0xd00000>;
+ interrupt-parent = <&pcie0>;
+ interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
+ 36 37>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0xffffffff>;
+ interrupt-map = <0 0 0 0 &intc 0 141 0
+ 0 0 0 1 &intc 0 149 0
+ 0 0 0 2 &intc 0 150 0
+ 0 0 0 3 &intc 0 151 0
+ 0 0 0 4 &intc 0 152 0
+ 0 0 0 5 &intc 0 140 0
+ 0 0 0 6 &intc 0 672 0
+ 0 0 0 7 &intc 0 673 0
+ 0 0 0 8 &intc 0 674 0
+ 0 0 0 9 &intc 0 675 0
+ 0 0 0 10 &intc 0 676 0
+ 0 0 0 11 &intc 0 677 0
+ 0 0 0 12 &intc 0 678 0
+ 0 0 0 13 &intc 0 679 0
+ 0 0 0 14 &intc 0 680 0
+ 0 0 0 15 &intc 0 681 0
+ 0 0 0 16 &intc 0 682 0
+ 0 0 0 17 &intc 0 683 0
+ 0 0 0 18 &intc 0 684 0
+ 0 0 0 19 &intc 0 685 0
+ 0 0 0 20 &intc 0 686 0
+ 0 0 0 21 &intc 0 687 0
+ 0 0 0 22 &intc 0 688 0
+ 0 0 0 23 &intc 0 689 0
+ 0 0 0 24 &intc 0 690 0
+ 0 0 0 25 &intc 0 691 0
+ 0 0 0 26 &intc 0 692 0
+ 0 0 0 27 &intc 0 693 0
+ 0 0 0 28 &intc 0 694 0
+ 0 0 0 29 &intc 0 695 0
+ 0 0 0 30 &intc 0 696 0
+ 0 0 0 31 &intc 0 697 0
+ 0 0 0 32 &intc 0 698 0
+ 0 0 0 33 &intc 0 699 0
+ 0 0 0 34 &intc 0 700 0
+ 0 0 0 35 &intc 0 701 0
+ 0 0 0 36 &intc 0 702 0
+ 0 0 0 37 &intc 0 703 0>;
+
+ interrupt-names = "int_msi", "int_a", "int_b", "int_c",
+ "int_d", "int_global_int",
+ "msi_0", "msi_1", "msi_2", "msi_3",
+ "msi_4", "msi_5", "msi_6", "msi_7",
+ "msi_8", "msi_9", "msi_10", "msi_11",
+ "msi_12", "msi_13", "msi_14", "msi_15",
+ "msi_16", "msi_17", "msi_18", "msi_19",
+ "msi_20", "msi_21", "msi_22", "msi_23",
+ "msi_24", "msi_25", "msi_26", "msi_27",
+ "msi_28", "msi_29", "msi_30", "msi_31";
+
+ qcom,phy-sequence = <0x804 0x01 0x0
+ 0x034 0x14 0x0
+ 0x138 0x30 0x0
+ 0x048 0x07 0x0
+ 0x15c 0x06 0x0
+ 0x090 0x01 0x0
+ 0x088 0x20 0x0
+ 0x0f0 0x00 0x0
+ 0x0f8 0x01 0x0
+ 0x0f4 0xc9 0x0
+ 0x11c 0xff 0x0
+ 0x120 0x3f 0x0
+ 0x164 0x01 0x0
+ 0x154 0x00 0x0
+ 0x148 0x0a 0x0
+ 0x05c 0x19 0x0
+ 0x038 0x90 0x0
+ 0x0b0 0x82 0x0
+ 0x0c0 0x02 0x0
+ 0x0bc 0xea 0x0
+ 0x0b8 0xab 0x0
+ 0x0a0 0x00 0x0
+ 0x09c 0x0d 0x0
+ 0x098 0x04 0x0
+ 0x13c 0x00 0x0
+ 0x060 0x06 0x0
+ 0x068 0x16 0x0
+ 0x070 0x36 0x0
+ 0x184 0x01 0x0
+ 0x15c 0x16 0x0
+ 0x138 0x33 0x0
+ 0x03c 0x02 0x0
+ 0x040 0x07 0x0
+ 0x080 0x04 0x0
+ 0x0dc 0x00 0x0
+ 0x0d8 0x3f 0x0
+ 0x00c 0x09 0x0
+ 0x010 0x01 0x0
+ 0x01c 0x40 0x0
+ 0x020 0x01 0x0
+ 0x014 0x02 0x0
+ 0x018 0x00 0x0
+ 0x024 0x7e 0x0
+ 0x028 0x15 0x0
+ 0x244 0x02 0x0
+ 0x2a4 0x12 0x0
+ 0x260 0x10 0x0
+ 0x28c 0x06 0x0
+ 0x504 0x03 0x0
+ 0x500 0x1c 0x0
+ 0x50c 0x14 0x0
+ 0x4d4 0x0e 0x0
+ 0x4d8 0x04 0x0
+ 0x4dc 0x1a 0x0
+ 0x434 0x4b 0x0
+ 0x414 0x04 0x0
+ 0x40c 0x04 0x0
+ 0x4f8 0x71 0x0
+ 0x564 0x59 0x0
+ 0x568 0x59 0x0
+ 0x4fc 0x80 0x0
+ 0x51c 0x40 0x0
+ 0x444 0x71 0x0
+ 0x43c 0x40 0x0
+ 0x854 0x04 0x0
+ 0x62c 0x52 0x0
+ 0x654 0x50 0x0
+ 0x65c 0x1a 0x0
+ 0x660 0x06 0x0
+ 0x8c8 0x83 0x0
+ 0x8cc 0x09 0x0
+ 0x8d0 0xa2 0x0
+ 0x8d4 0x40 0x0
+ 0x8c4 0x02 0x0
+ 0x9ac 0x00 0x0
+ 0x8a0 0x01 0x0
+ 0x9e0 0x00 0x0
+ 0x9dc 0x20 0x0
+ 0x9a8 0x00 0x0
+ 0x8a4 0x01 0x0
+ 0x8a8 0x73 0x0
+ 0x9d8 0xaa 0x0
+ 0x9b0 0x03 0x0
+ 0xa0c 0x0d 0x0
+ 0x86c 0x00 0x0
+ 0x644 0x00 0x0
+ 0x804 0x03 0x0
+ 0x800 0x00 0x0
+ 0x808 0x03 0x0>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_clkreq_default
+ &pcie0_perst_default
+ &pcie0_wake_default>;
+
+ perst-gpio = <&tlmm 35 0>;
+ wake-gpio = <&tlmm 37 0>;
+
+ gdsc-vdd-supply = <&pcie_0_gdsc>;
+ vreg-1.8-supply = <&pm8998_l26>;
+ vreg-0.9-supply = <&pm8998_l1>;
+ vreg-cx-supply = <&pm8998_s9_level>;
+
+ qcom,vreg-1.8-voltage-level = <1200000 1200000 24000>;
+ qcom,vreg-0.9-voltage-level = <880000 880000 24000>;
+ qcom,vreg-cx-voltage-level = <RPMH_REGULATOR_LEVEL_MAX
+ RPMH_REGULATOR_LEVEL_SVS 0>;
+
+ qcom,l1-supported;
+ qcom,l1ss-supported;
+ qcom,aux-clk-sync;
+
+ qcom,ep-latency = <10>;
+
+ qcom,boot-option = <0x1>;
+
+ linux,pci-domain = <0>;
+
+ qcom,msi-gicm-addr = <0x17a00040>;
+ qcom,msi-gicm-base = <0x2c0>;
+
+ qcom,pcie-phy-ver = <0x30>;
+ qcom,use-19p2mhz-aux-clk;
+
+ qcom,smmu-sid-base = <0x1c10>;
+
+ iommu-map = <0x100 &apps_smmu 0x1c11 0x1>,
+ <0x200 &apps_smmu 0x1c12 0x1>,
+ <0x300 &apps_smmu 0x1c13 0x1>,
+ <0x400 &apps_smmu 0x1c14 0x1>,
+ <0x500 &apps_smmu 0x1c15 0x1>,
+ <0x600 &apps_smmu 0x1c16 0x1>,
+ <0x700 &apps_smmu 0x1c17 0x1>,
+ <0x800 &apps_smmu 0x1c18 0x1>,
+ <0x900 &apps_smmu 0x1c19 0x1>,
+ <0xa00 &apps_smmu 0x1c1a 0x1>,
+ <0xb00 &apps_smmu 0x1c1b 0x1>,
+ <0xc00 &apps_smmu 0x1c1c 0x1>,
+ <0xd00 &apps_smmu 0x1c1d 0x1>,
+ <0xe00 &apps_smmu 0x1c1e 0x1>,
+ <0xf00 &apps_smmu 0x1c1f 0x1>;
+
+ qcom,msm-bus,name = "pcie0";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <45 512 0 0>,
+ <45 512 500 800>;
+
+ clocks = <&clock_gcc GCC_PCIE_0_PIPE_CLK>,
+ <&clock_rpmh RPMH_CXO_CLK>,
+ <&clock_gcc GCC_PCIE_0_AUX_CLK>,
+ <&clock_gcc GCC_PCIE_0_CFG_AHB_CLK>,
+ <&clock_gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+ <&clock_gcc GCC_PCIE_0_SLV_AXI_CLK>,
+ <&clock_gcc GCC_PCIE_0_CLKREF_CLK>,
+ <&clock_gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>,
+ <&clock_gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>,
+ <&clock_gcc GCC_PCIE_PHY_REFGEN_CLK>,
+ <&clock_gcc GCC_PCIE_PHY_AUX_CLK>;
+
+ clock-names = "pcie_0_pipe_clk", "pcie_0_ref_clk_src",
+ "pcie_0_aux_clk", "pcie_0_cfg_ahb_clk",
+ "pcie_0_mstr_axi_clk", "pcie_0_slv_axi_clk",
+ "pcie_0_ldo", "pcie_0_slv_q2a_axi_clk",
+ "pcie_tbu_clk", "pcie_phy_refgen_clk",
+ "pcie_phy_aux_clk";
+
+ max-clock-frequency-hz = <0>, <0>, <19200000>, <0>, <0>,
+ <0>, <0>, <0>, <0>, <100000000>, <0>;
+
+ resets = <&clock_gcc GCC_PCIE_0_BCR>,
+ <&clock_gcc GCC_PCIE_0_PHY_BCR>;
+
+ reset-names = "pcie_0_core_reset",
+ "pcie_0_phy_reset";
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
index bc535d1..3ab0c70 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
@@ -160,6 +160,47 @@
};
};
+ pcie0 {
+ pcie0_clkreq_default: pcie0_clkreq_default {
+ mux {
+ pins = "gpio36";
+ function = "pci_e0";
+ };
+
+ config {
+ pins = "gpio36";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie0_perst_default: pcie0_perst_default {
+ mux {
+ pins = "gpio35";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio35";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+
+ pcie0_wake_default: pcie0_wake_default {
+ mux {
+ pins = "gpio37";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio37";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+ };
+
cdc_reset_ctrl {
cdc_reset_sleep: cdc_reset_sleep {
mux {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
index dd0d08e..e5d1a74 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
@@ -30,9 +30,11 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&qupv3_se6_4uart_active>;
pinctrl-1 = <&qupv3_se6_4uart_sleep>;
- interrupts = <GIC_SPI 607 0>;
+ interrupts-extended = <&intc GIC_SPI 607 0>,
+ <&tlmm 48 0>;
status = "disabled";
qcom,bus-mas = <MSM_BUS_MASTER_BLSP_1>;
+ qcom,wakeup-byte = <0xFD>;
};
qupv3_se7_4uart: qcom,qup_uart@0x89c000 {
@@ -46,9 +48,11 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&qupv3_se7_4uart_active>;
pinctrl-1 = <&qupv3_se7_4uart_sleep>;
- interrupts = <GIC_SPI 608 0>;
+ interrupts-extended = <&intc GIC_SPI 608 0>,
+ <&tlmm 96 0>;
status = "disabled";
qcom,bus-mas = <MSM_BUS_MASTER_BLSP_1>;
+ qcom,wakeup-byte = <0xFD>;
};
/* I2C */
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
index 7f24c8b..efd8f45 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
@@ -116,6 +116,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_sharp_4k_dsc_video>;
vddio-supply = <&pm8998_l14>;
@@ -139,6 +140,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_sharp_4k_dsc_cmd>;
vddio-supply = <&pm8998_l14>;
@@ -162,6 +164,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_sharp_1080_cmd>;
vddio-supply = <&pm8998_l14>;
@@ -185,6 +188,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_dual_sharp_1080_120hz_cmd>;
vddio-supply = <&pm8998_l14>;
@@ -231,6 +235,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_dual_nt35597_truly_cmd>;
vddio-supply = <&pm8998_l14>;
@@ -254,6 +259,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_nt35597_truly_dsc_cmd>;
vddio-supply = <&pm8998_l14>;
@@ -277,6 +283,7 @@
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_nt35597_truly_dsc_video>;
vddio-supply = <&pm8998_l14>;
@@ -296,43 +303,43 @@
};
&dsi_dual_nt35597_truly_video {
- qcom,mdss-dsi-panel-timings = [00 1c 07 07 23 21 07 07 05 03 04];
+ qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07 07 05 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x0D>;
qcom,mdss-dsi-t-clk-pre = <0x2D>;
};
&dsi_dual_nt35597_truly_cmd {
- qcom,mdss-dsi-panel-timings = [00 1c 07 07 23 21 07 07 05 03 04];
+ qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07 07 05 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x0D>;
qcom,mdss-dsi-t-clk-pre = <0x2D>;
};
&dsi_nt35597_truly_dsc_cmd {
- qcom,mdss-dsi-panel-timings = [00 15 05 05 20 1f 05 05 03 03 04];
+ qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05 05 03 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x0b>;
qcom,mdss-dsi-t-clk-pre = <0x23>;
};
&dsi_nt35597_truly_dsc_video {
- qcom,mdss-dsi-panel-timings = [00 15 05 05 20 1f 05 05 03 03 04];
+ qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05 05 03 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x0b>;
qcom,mdss-dsi-t-clk-pre = <0x23>;
};
&dsi_sharp_4k_dsc_video {
- qcom,mdss-dsi-panel-timings = [00 12 04 04 1e 1e 04 04 02 03 04];
- qcom,mdss-dsi-t-clk-post = <0x0a>;
- qcom,mdss-dsi-t-clk-pre = <0x1e>;
+ qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06 06 04 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x0c>;
+ qcom,mdss-dsi-t-clk-pre = <0x27>;
};
&dsi_sharp_4k_dsc_cmd {
- qcom,mdss-dsi-panel-timings = [00 12 04 04 1e 1e 04 04 02 03 04];
- qcom,mdss-dsi-t-clk-post = <0x0a>;
- qcom,mdss-dsi-t-clk-pre = <0x1e>;
+ qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06 06 04 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x0c>;
+ qcom,mdss-dsi-t-clk-pre = <0x27>;
};
&dsi_dual_sharp_1080_120hz_cmd {
- qcom,mdss-dsi-panel-timings = [00 24 09 09 26 24 09 09 06 03 04];
+ qcom,mdss-dsi-panel-phy-timings = [00 24 09 09 26 24 09 09 06 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x0f>;
qcom,mdss-dsi-t-clk-pre = <0x36>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index 5088f0f..af63d22 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -97,8 +97,6 @@
1 5 9 13>;
qcom,sde-sspp-excl-rect = <1 1 1 1
1 1 1 1>;
- qcom,sde-sspp-smart-dma-priority = <5 6 7 8 1 2 3 4>;
- qcom,sde-smart-dma-rev = "smart_dma_v2";
qcom,sde-mixer-pair-mask = <2 1 6 0 0 3>;
@@ -120,6 +118,7 @@
qcom,sde-highest-bank-bit = <0x2>;
qcom,sde-ubwc-version = <0x200>;
qcom,sde-ubwc-static = <0x100>;
+ qcom,sde-ubwc-swizzle = <1>;
qcom,sde-panic-per-pipe;
qcom,sde-has-cdp;
qcom,sde-has-src-split;
@@ -210,7 +209,6 @@
};
mdss_rotator: qcom,mdss_rotator@ae00000 {
- status = "disabled";
compatible = "qcom,sde_rotator";
reg = <0x0ae00000 0xac000>,
<0x0aeb8000 0x3000>;
@@ -261,14 +259,11 @@
smmu_rot_unsec: qcom,smmu_rot_unsec_cb {
compatible = "qcom,smmu_sde_rot_unsec";
iommus = <&apps_smmu 0x1090 0x0>;
- gdsc-mdss-supply = <&hlos1_vote_mmnoc_mmu_tbu_sf_gdsc>;
};
smmu_rot_sec: qcom,smmu_rot_sec_cb {
- status = "disabled";
compatible = "qcom,smmu_sde_rot_sec";
iommus = <&apps_smmu 0x1091 0x0>;
- gdsc-mdss-supply = <&hlos1_vote_mmnoc_mmu_tbu_sf_gdsc>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 87d8a56..72c2efa 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -34,6 +34,7 @@
aliases {
ufshc1 = &ufshc_mem; /* Embedded UFS slot */
ufshc2 = &ufshc_card; /* Removable UFS slot */
+ pci-domain0 = &pcie0;
sdhc2 = &sdhc_2; /* SDC2 SD card slot */
};
@@ -1021,6 +1022,29 @@
mbox-names = "qdss_clk";
};
+ ufs_ice: ufsice@1d90000 {
+ compatible = "qcom,ice";
+ reg = <0x1d90000 0x8000>;
+ qcom,enable-ice-clk;
+ clock-names = "ufs_core_clk", "bus_clk",
+ "iface_clk", "ice_core_clk";
+ clocks = <&clock_gcc GCC_UFS_PHY_AXI_CLK>,
+ <&clock_gcc GCC_UFS_MEM_CLKREF_CLK>,
+ <&clock_gcc GCC_UFS_PHY_AHB_CLK>,
+ <&clock_gcc GCC_UFS_PHY_ICE_CORE_CLK>;
+ qcom,op-freq-hz = <0>, <0>, <0>, <300000000>;
+ vdd-hba-supply = <&ufs_phy_gdsc>;
+ qcom,msm-bus,name = "ufs_ice_noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <1 650 0 0>, /* No vote */
+ <1 650 1000 0>; /* Max. bandwidth */
+ qcom,bus-vector-names = "MIN",
+ "MAX";
+ qcom,instance-type = "ufs";
+ };
+
ufsphy_mem: ufsphy_mem@1d87000 {
reg = <0x1d87000 0xda8>; /* PHY regs */
reg-names = "phy_mem";
@@ -1038,12 +1062,13 @@
status = "disabled";
};
- ufshc_mem: ufshc_mem@1d84000 {
+ ufshc_mem: ufshc@1d84000 {
compatible = "qcom,ufshc";
reg = <0x1d84000 0x2500>;
interrupts = <0 265 0>;
phys = <&ufsphy_mem>;
phy-names = "ufsphy";
+ ufs-qcom-crypto = <&ufs_ice>;
lanes-per-direction = <2>;
dev-ref-clk-freq = <0>; /* 19.2 MHz */
@@ -1422,6 +1447,7 @@
};
slim_qca: slim@17240000 {
+ status = "ok";
cell-index = <3>;
compatible = "qcom,slim-ngd";
reg = <0x17240000 0x2c000>,
@@ -1429,6 +1455,14 @@
reg-names = "slimbus_physical", "slimbus_bam_physical";
interrupts = <0 291 0>, <0 292 0>;
interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+
+ /* Slimbus Slave DT for WCN3990 */
+ btfmslim_codec: wcn3990 {
+ compatible = "qcom,btfmslim_slave";
+ elemental-addr = [00 01 20 02 17 02];
+ qcom,btfm-slim-ifd = "btfmslim_slave_ifd";
+ qcom,btfm-slim-ifd-elemental-addr = [00 00 20 02 17 02];
+ };
};
eud: qcom,msm-eud@88e0000 {
@@ -2151,6 +2185,65 @@
hyplog-size-offset = <0x414>;
};
+ qcom_cedev: qcedev@1de0000 {
+ compatible = "qcom,qcedev";
+ reg = <0x1de0000 0x20000>,
+ <0x1dc4000 0x24000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 272 0>;
+ qcom,bam-pipe-pair = <1>;
+ qcom,ce-hw-instance = <0>;
+ qcom,ce-device = <0>;
+ qcom,ce-hw-shared;
+ qcom,bam-ee = <0>;
+ qcom,msm-bus,name = "qcedev-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <125 512 0 0>,
+ <125 512 393600 393600>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ clocks = <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_AHB_CLK>,
+ <&clock_gcc GCC_CE1_AXI_CLK>;
+ qcom,ce-opp-freq = <171430000>;
+ };
+
+ qcom_crypto: qcrypto@1de0000 {
+ compatible = "qcom,qcrypto";
+ reg = <0x1de0000 0x20000>,
+ <0x1dc4000 0x24000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 272 0>;
+ qcom,bam-pipe-pair = <2>;
+ qcom,ce-hw-instance = <0>;
+ qcom,ce-device = <0>;
+ qcom,bam-ee = <0>;
+ qcom,ce-hw-shared;
+ qcom,clk-mgmt-sus-res;
+ qcom,msm-bus,name = "qcrypto-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <125 512 0 0>,
+ <125 512 393600 393600>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ clocks = <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_AHB_CLK>,
+ <&clock_gcc GCC_CE1_AXI_CLK>;
+ qcom,ce-opp-freq = <171430000>;
+ qcom,use-sw-aes-cbc-ecb-ctr-algo;
+ qcom,use-sw-aes-xts-algo;
+ qcom,use-sw-aes-ccm-algo;
+ qcom,use-sw-ahash-algo;
+ qcom,use-sw-aead-algo;
+ qcom,use-sw-hmac-algo;
+ };
+
qcom,msm_gsi {
compatible = "qcom,msm_gsi";
};
@@ -3556,6 +3649,7 @@
#include "sdm845-vidc.dtsi"
#include "sdm845-pm.dtsi"
#include "sdm845-pinctrl.dtsi"
+#include "sdm845-pcie.dtsi"
#include "sdm845-audio.dtsi"
#include "sdm845-gpu.dtsi"
#include "sdm845-usb.dtsi"
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index c5cfa18..f989858 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -49,6 +49,7 @@
CONFIG_ARCH_SDM845=y
CONFIG_ARCH_SDM830=y
CONFIG_PCI=y
+CONFIG_PCI_MSM=y
CONFIG_SCHED_MC=y
CONFIG_NR_CPUS=8
CONFIG_PREEMPT=y
@@ -238,6 +239,7 @@
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
@@ -336,6 +338,7 @@
CONFIG_MSM_VIDC_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_QCOM_KGSL=y
CONFIG_DRM=y
CONFIG_DRM_SDE_EVTLOG_DEBUG=y
CONFIG_DRM_SDE_RSC=y
@@ -445,6 +448,8 @@
CONFIG_QCOM_RUN_QUEUE_STATS=y
CONFIG_QCOM_LLCC=y
CONFIG_QCOM_SDM845_LLCC=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_QCOM_EUD=y
CONFIG_QCOM_WATCHDOG_V2=y
@@ -474,10 +479,12 @@
CONFIG_ICNSS=y
CONFIG_QCOM_COMMAND_DB=y
CONFIG_MSM_ADSP_LOADER=y
+CONFIG_MSM_CDSP_LOADER=y
CONFIG_MSM_AVTIMER=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_PM=y
CONFIG_APSS_CORE_EA=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
CONFIG_QCOMCCI_HWMON=y
@@ -537,7 +544,10 @@
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_ANSI_CPRNG=y
-CONFIG_CRYPTO_DEV_QCE=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
CONFIG_ARM64_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 100ca68..7136ca8 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -54,12 +54,14 @@
CONFIG_ARCH_SDM845=y
CONFIG_ARCH_SDM830=y
CONFIG_PCI=y
+CONFIG_PCI_MSM=y
CONFIG_SCHED_MC=y
CONFIG_NR_CPUS=8
CONFIG_PREEMPT=y
CONFIG_HZ_100=y
CONFIG_CLEANCACHE=y
CONFIG_CMA=y
+CONFIG_CMA_DEBUGFS=y
CONFIG_ZSMALLOC=y
CONFIG_BALANCE_ANON_FILE_RECLAIM=y
CONFIG_SECCOMP=y
@@ -248,6 +250,7 @@
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
@@ -462,6 +465,8 @@
CONFIG_QCOM_RUN_QUEUE_STATS=y
CONFIG_QCOM_LLCC=y
CONFIG_QCOM_SDM845_LLCC=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
CONFIG_MSM_GLADIATOR_HANG_DETECT=y
@@ -494,11 +499,13 @@
CONFIG_ICNSS_DEBUG=y
CONFIG_QCOM_COMMAND_DB=y
CONFIG_MSM_ADSP_LOADER=y
+CONFIG_MSM_CDSP_LOADER=y
CONFIG_MSM_AVTIMER=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_PM=y
CONFIG_APSS_CORE_EA=y
CONFIG_QCOM_DCC_V2=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
CONFIG_QCOMCCI_HWMON=y
@@ -607,7 +614,10 @@
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_ANSI_CPRNG=y
-CONFIG_CRYPTO_DEV_QCE=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
CONFIG_ARM64_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 804d2a2..dd6a18b 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -80,7 +80,7 @@
}
/* Sorted insert of 75th percentile into buf2 */
- for (k = 0; k < i; ++k) {
+ for (k = 0; k < i && k < ARRAY_SIZE(buf2); ++k) {
if (buf1[ARRAY_SIZE(buf1) - 1] < buf2[k]) {
l = min_t(unsigned int,
i, ARRAY_SIZE(buf2) - 1);
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index 6430bff..5c429d7 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -257,7 +257,7 @@
else if ((prog_req.fr1 && prog_req.frdefault) ||
(prog_req.single && !prog_req.frdefault))
/* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */
- state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
+ state->overall_fp_mode = ((raw_current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
cpu_has_mips_r2_r6) ?
FP_FR1 : FP_FR0;
else if (prog_req.fr1)
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index de63d36..732d617 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -244,9 +244,6 @@
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{
int reg;
- struct thread_info *ti = task_thread_info(p);
- unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32;
- struct pt_regs *regs = (struct pt_regs *)ksp - 1;
#if (KGDB_GDB_REG_SIZE == 32)
u32 *ptr = (u32 *)gdb_regs;
#else
@@ -254,25 +251,46 @@
#endif
for (reg = 0; reg < 16; reg++)
- *(ptr++) = regs->regs[reg];
+ *(ptr++) = 0;
/* S0 - S7 */
- for (reg = 16; reg < 24; reg++)
- *(ptr++) = regs->regs[reg];
+ *(ptr++) = p->thread.reg16;
+ *(ptr++) = p->thread.reg17;
+ *(ptr++) = p->thread.reg18;
+ *(ptr++) = p->thread.reg19;
+ *(ptr++) = p->thread.reg20;
+ *(ptr++) = p->thread.reg21;
+ *(ptr++) = p->thread.reg22;
+ *(ptr++) = p->thread.reg23;
for (reg = 24; reg < 28; reg++)
*(ptr++) = 0;
/* GP, SP, FP, RA */
- for (reg = 28; reg < 32; reg++)
- *(ptr++) = regs->regs[reg];
+ *(ptr++) = (long)p;
+ *(ptr++) = p->thread.reg29;
+ *(ptr++) = p->thread.reg30;
+ *(ptr++) = p->thread.reg31;
- *(ptr++) = regs->cp0_status;
- *(ptr++) = regs->lo;
- *(ptr++) = regs->hi;
- *(ptr++) = regs->cp0_badvaddr;
- *(ptr++) = regs->cp0_cause;
- *(ptr++) = regs->cp0_epc;
+ *(ptr++) = p->thread.cp0_status;
+
+ /* lo, hi */
+ *(ptr++) = 0;
+ *(ptr++) = 0;
+
+ /*
+ * BadVAddr, Cause
+ * Ideally these would come from the last exception frame up the stack
+ * but that requires unwinding, otherwise we can't know much for sure.
+ */
+ *(ptr++) = 0;
+ *(ptr++) = 0;
+
+ /*
+ * PC
+ * use return address (RA), i.e. the moment after return from resume()
+ */
+ *(ptr++) = p->thread.reg31;
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 1fb317f..b6802b9 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -673,6 +673,14 @@
return pte_pfn(pte);
}
+#define __HAVE_ARCH_PMD_WRITE
+static inline unsigned long pmd_write(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ return pte_write(pte);
+}
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static inline unsigned long pmd_dirty(pmd_t pmd)
{
@@ -688,13 +696,6 @@
return pte_young(pte);
}
-static inline unsigned long pmd_write(pmd_t pmd)
-{
- pte_t pte = __pte(pmd_val(pmd));
-
- return pte_write(pte);
-}
-
static inline unsigned long pmd_trans_huge(pmd_t pmd)
{
pte_t pte = __pte(pmd_val(pmd));
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 37aa537..bd7e2aa 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1495,7 +1495,7 @@
if ((long)addr < 0L) {
unsigned long pa = __pa(addr);
- if ((addr >> max_phys_bits) != 0UL)
+ if ((pa >> max_phys_bits) != 0UL)
return false;
return pfn_valid(pa >> PAGE_SHIFT);
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 8639bb2..6bf09f5 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -983,6 +983,18 @@
unsigned long return_hooker = (unsigned long)
&return_to_handler;
+ /*
+ * When resuming from suspend-to-ram, this function can be indirectly
+ * called from early CPU startup code while the CPU is in real mode,
+ * which would fail miserably. Make sure the stack pointer is a
+ * virtual address.
+ *
+ * This check isn't as accurate as virt_addr_valid(), but it should be
+ * good enough for this purpose, and it's fast.
+ */
+ if (unlikely((long)__builtin_frame_address(0) >= 0))
+ return;
+
if (unlikely(ftrace_graph_is_dead()))
return;
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index fd02eba..f61b78a 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -385,58 +385,6 @@
Select this to offload Samsung S5PV210 or S5PC110, Exynos from AES
algorithms execution.
-config CRYPTO_DEV_QCE50
- bool
-
-config FIPS_ENABLE
- bool "FIPS140-2 compliant build"
- default n
- help
- This flag is used to make current build FIPS140-2
- compliant. This flag will enable the patch of code
- which will perform this task. Please select Y here
- to enable.
-
-config CRYPTO_DEV_QCRYPTO
- tristate "QTI Crypto accelerator"
- select CRYPTO_DES
- select CRYPTO_ALGAPI
- select CRYPTO_AUTHENC
- select CRYPTO_BLKCIPHER
- default n
- help
- This driver supports QTI crypto acceleration
- for kernel clients. To compile this driver as a module,
- choose M here: the module will be called qcrypto. Please
- select Y here to enable.
-
-config CRYPTO_DEV_QCOM_MSM_QCE
- tristate "QTI Crypto Engine (QCE) module"
- default n
- help
- This driver supports QTI Crypto Engine 5.0.
- To compile this driver as a module, choose M here: the
- module is called qce50.
-
-config CRYPTO_DEV_QCEDEV
- tristate "QCEDEV Interface to CE module"
- default n
- help
- This driver supports QTI QCEDEV Crypto Engine 5.0.
- This exposes the interface to the QCE hardware accelerator
- via IOCTLs.
-
- To compile this driver as a module, choose M here: the
- module will be called qcedev.
-
-config CRYPTO_DEV_OTA_CRYPTO
- tristate "OTA Crypto module"
- help
- This driver supports QTI OTA Crypto in the FSM9xxx.
- To compile this driver as a module, choose M here: the
- module will be called ota_crypto. Please select Y here
- to enable.
-
config CRYPTO_DEV_NX
bool "Support for IBM PowerPC Nest (NX) cryptographic acceleration"
depends on PPC64
@@ -550,7 +498,49 @@
help
This driver supports Qualcomm crypto engine accelerator
hardware. To compile this driver as a module, choose M here. The
- module will be called qcrypto.
+ module will be called qcrypt.
+
+config CRYPTO_DEV_QCOM_MSM_QCE
+ tristate "QTI Crypto Engine (QCE) module"
+ depends on ARCH_QCOM
+ help
+ This driver supports QTI Crypto Engine accelerator hardware, which
+ is present on SDM845. This is the core crypto driver which adds
+ CE5.0 functionalities. To compile this driver as a module, choose
+ M here. The module will be called QCE50.
+
+config CRYPTO_DEV_QCRYPTO
+ tristate "QTI Crypto accelerator"
+ depends on ARCH_QCOM
+ select CRYPTO_DES
+ select CRYPTO_ALGAPI
+ select CRYPTO_AUTHENC
+ select CRYPTO_BLKCIPHER
+ help
+ This driver supports QTI crypto acceleration
+ for kernel clients. To compile this driver as a module,
+ choose M here: the module will be called qcrypto. Please
+ select Y here to enable.
+
+config CRYPTO_DEV_QCEDEV
+ tristate "QCEDEV Interface to CE module"
+ depends on ARCH_QCOM
+ help
+ This driver supports QTI QCEDEV Crypto Engine 5.0.
+ This exposes the interface to the QCE hardware accelerator
+ via IOCTLs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called qcedev.
+
+config CRYPTO_DEV_OTA_CRYPTO
+ tristate "OTA Crypto module"
+ depends on ARCH_QCOM
+ help
+ This driver supports QTI OTA Crypto in the FSM9xxx.
+ To compile this driver as a module, choose M here: the
+ module will be called ota_crypto. Please select Y here
+ to enable.
config CRYPTO_DEV_VMX
bool "Support for VMX cryptographic acceleration instructions"
diff --git a/drivers/crypto/msm/Kconfig b/drivers/crypto/msm/Kconfig
index 0f4568b..3011aa6 100644
--- a/drivers/crypto/msm/Kconfig
+++ b/drivers/crypto/msm/Kconfig
@@ -2,7 +2,7 @@
config CRYPTO_DEV_QCOM_ICE
tristate "Inline Crypto Module"
default n
- depends on PFK && BLK_DEV_DM
+ depends on BLK_DEV_DM
help
This driver supports Inline Crypto Engine for QTI chipsets, MSM8994
and later, to accelerate crypto operations for storage needs.
diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c
index ba6825e..b411726 100644
--- a/drivers/crypto/msm/ice.c
+++ b/drivers/crypto/msm/ice.c
@@ -21,12 +21,31 @@
#include <linux/cdev.h>
#include <linux/regulator/consumer.h>
#include <linux/msm-bus.h>
-#include <linux/pfk.h>
#include <crypto/ice.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/qseecomi.h>
#include "iceregs.h"
+#ifdef CONFIG_PFK
+#include <linux/pfk.h>
+#else
+#include <linux/bio.h>
+static inline int pfk_load_key_start(const struct bio *bio,
+ struct ice_crypto_setting *ice_setting, bool *is_pfe, bool async)
+{
+ return 0;
+}
+
+static inline int pfk_load_key_end(const struct bio *bio, bool *is_pfe)
+{
+ return 0;
+}
+
+static inline void pfk_clear_on_reset(void)
+{
+}
+#endif
+
#define TZ_SYSCALL_CREATE_SMC_ID(o, s, f) \
((uint32_t)((((o & 0x3f) << 24) | (s & 0xff) << 8) | (f & 0xff)))
diff --git a/drivers/crypto/qce/Makefile b/drivers/crypto/qce/Makefile
index 348dc31..7f584ee 100644
--- a/drivers/crypto/qce/Makefile
+++ b/drivers/crypto/qce/Makefile
@@ -1,5 +1,5 @@
-obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o
-qcrypto-objs := core.o \
+obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypt.o
+qcrypt-objs := core.o \
common.o \
dma.o \
sha.o \
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
index ee39ec7..563285d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
@@ -408,6 +408,7 @@
u32 pixel_clk_khz;
enum dsi_op_mode panel_mode;
u32 dsi_mode_flags;
+ struct msm_mode_info *mode_info;
};
#endif /* _DSI_DEFS_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 556c0d8..3f4bb5a5 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -50,6 +50,8 @@
dsi_mode->pixel_clk_khz = drm_mode->clock;
dsi_mode->panel_mode = 0; /* TODO: Panel Mode */
+ dsi_mode->mode_info = (struct msm_mode_info *)drm_mode->private;
+
if (msm_is_mode_seamless(drm_mode))
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_SEAMLESS;
if (msm_is_mode_dynamic_fps(drm_mode))
@@ -81,6 +83,8 @@
drm_mode->vrefresh = dsi_mode->timing.refresh_rate;
drm_mode->clock = dsi_mode->pixel_clk_khz;
+ drm_mode->private = (int *)dsi_mode->mode_info;
+
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_SEAMLESS)
drm_mode->flags |= DRM_MODE_FLAG_SEAMLESS;
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DFPS)
@@ -255,6 +259,26 @@
return ret;
}
+int dsi_conn_get_topology(const struct drm_display_mode *drm_mode,
+ struct msm_display_topology *topology,
+ u32 max_mixer_width)
+{
+ struct dsi_display_mode dsi_mode;
+
+ if (!drm_mode || !topology)
+ return -EINVAL;
+
+ convert_to_dsi_mode(drm_mode, &dsi_mode);
+
+ if (!dsi_mode.mode_info)
+ return -EINVAL;
+
+ memcpy(topology, &dsi_mode.mode_info->topology,
+ sizeof(struct msm_display_topology));
+
+ return 0;
+}
+
static const struct drm_bridge_funcs dsi_bridge_ops = {
.attach = dsi_bridge_attach,
.mode_fixup = dsi_bridge_mode_fixup,
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
index 4339a11..68520a8 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
@@ -64,6 +64,17 @@
void *display);
/**
+ * dsi_conn_get_topology - retrieve current topology for the mode selected
+ * @drm_mode: Display mode set for the display
+ * @topology: Out parameter. Topology for the mode.
+ * @max_mixer_width: max width supported by HW layer mixer
+ * Returns: Zero on success
+ */
+int dsi_conn_get_topology(const struct drm_display_mode *drm_mode,
+ struct msm_display_topology *topology,
+ u32 max_mixer_width);
+
+/**
* dsi_conn_mode_valid - callback to determine if specified mode is valid
* @connector: Pointer to drm connector structure
* @mode: Pointer to drm mode structure
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index b814eb8..cb4afe4 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -20,6 +20,19 @@
#include "dsi_panel.h"
#include "dsi_ctrl_hw.h"
+#define MAX_CMDLINE_PARAM_LEN 256
+static char display_config[MAX_CMDLINE_PARAM_LEN];
+
+/**
+ * topology is currently defined by a set of following 3 values:
+ * 1. num of layer mixers
+ * 2. num of compression encoders
+ * 3. num of interfaces
+ */
+#define TOPOLOGY_SET_LEN 3
+#define INT_BASE_10 10
+#define MAX_TOPOLOGY 5
+
#define DSI_PANEL_DEFAULT_LABEL "Default dsi panel"
#define DEFAULT_MDP_TRANSFER_TIME 14000
@@ -1912,25 +1925,18 @@
u32 data;
int rc = -EINVAL;
int intf_width;
- struct device_node *dsc_np = NULL;
if (!panel->dsc_enabled)
return 0;
- dsc_np = of_parse_phandle(of_node, "qcom,config-select", 0);
- if (!dsc_np) {
- pr_err("no dsc config found\n");
- goto error;
- }
-
- rc = of_property_read_u32(dsc_np, "qcom,mdss-dsc-slice-height", &data);
+ rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-height", &data);
if (rc) {
pr_err("failed to parse qcom,mdss-dsc-slice-height\n");
goto error;
}
panel->dsc.slice_height = data;
- rc = of_property_read_u32(dsc_np, "qcom,mdss-dsc-slice-width", &data);
+ rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-width", &data);
if (rc) {
pr_err("failed to parse qcom,mdss-dsc-slice-width\n");
goto error;
@@ -1946,14 +1952,15 @@
panel->dsc.pic_width = panel->mode.timing.h_active;
panel->dsc.pic_height = panel->mode.timing.v_active;
- rc = of_property_read_u32(dsc_np, "qcom,mdss-dsc-slice-per-pkt", &data);
+ rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-per-pkt",
+ &data);
if (rc) {
pr_err("failed to parse qcom,mdss-dsc-slice-per-pkt\n");
goto error;
}
panel->dsc.slice_per_pkt = data;
- rc = of_property_read_u32(dsc_np, "qcom,mdss-dsc-bit-per-component",
+ rc = of_property_read_u32(of_node, "qcom,mdss-dsc-bit-per-component",
&data);
if (rc) {
pr_err("failed to parse qcom,mdss-dsc-bit-per-component\n");
@@ -1961,14 +1968,15 @@
}
panel->dsc.bpc = data;
- rc = of_property_read_u32(dsc_np, "qcom,mdss-dsc-bit-per-pixel", &data);
+ rc = of_property_read_u32(of_node, "qcom,mdss-dsc-bit-per-pixel",
+ &data);
if (rc) {
pr_err("failed to parse qcom,mdss-dsc-bit-per-pixel\n");
goto error;
}
panel->dsc.bpp = data;
- panel->dsc.block_pred_enable = of_property_read_bool(dsc_np,
+ panel->dsc.block_pred_enable = of_property_read_bool(of_node,
"qcom,mdss-dsc-block-prediction-enable");
panel->dsc.full_frame_slices = DIV_ROUND_UP(intf_width,
@@ -2027,6 +2035,112 @@
return 0;
}
+static int dsi_get_cmdline_top_override(void)
+{
+ char *str = display_config;
+ int top_index = -1;
+
+ /*
+ * This module need to be updated with needed cmd line argument parsing
+ * for other dsi parameters.
+ */
+ if (strlcat(str, "\0", sizeof(str)) > sizeof(str))
+ return -EINVAL;
+
+ str = strnstr(display_config, "config", strlen(display_config));
+ if (!str)
+ return -EINVAL;
+
+ if (kstrtol(str + strlen("config"), INT_BASE_10,
+ (unsigned long *)&top_index))
+ return -EINVAL;
+
+ return top_index;
+}
+
+static int dsi_panel_parse_topology(struct dsi_panel *panel,
+ struct device_node *of_node)
+{
+ struct msm_display_topology *topology;
+ u32 top_count, top_sel, *array = NULL;
+ int i, len = 0;
+ int rc = -EINVAL;
+
+ len = of_property_count_u32_elems(of_node, "qcom,display-topology");
+ if (len <= 0 || len % TOPOLOGY_SET_LEN ||
+ len > (TOPOLOGY_SET_LEN * MAX_TOPOLOGY)) {
+ pr_err("invalid topology list for the panel, rc = %d\n", rc);
+ return rc;
+ }
+
+ top_count = len / TOPOLOGY_SET_LEN;
+
+ array = kcalloc(len, sizeof(u32), GFP_KERNEL);
+ if (!array)
+ return -ENOMEM;
+
+ rc = of_property_read_u32_array(of_node,
+ "qcom,display-topology", array, len);
+ if (rc) {
+ pr_err("unable to read the display topologies, rc = %d\n", rc);
+ goto read_fail;
+ }
+
+ topology = kcalloc(top_count, sizeof(*topology), GFP_KERNEL);
+ if (!topology) {
+ rc = -ENOMEM;
+ goto read_fail;
+ }
+
+ for (i = 0; i < top_count; i++) {
+ struct msm_display_topology *top = &topology[i];
+
+ top->num_lm = array[i * TOPOLOGY_SET_LEN];
+ top->num_enc = array[i * TOPOLOGY_SET_LEN + 1];
+ top->num_intf = array[i * TOPOLOGY_SET_LEN + 2];
+ };
+
+ top_sel = dsi_get_cmdline_top_override();
+ if (top_sel >= 0 && top_sel < top_count) {
+ pr_info("overidden topology: lm: %d comp_enc:%d intf: %d\n",
+ topology[top_sel].num_lm,
+ topology[top_sel].num_enc,
+ topology[top_sel].num_intf);
+ goto parse_done;
+ }
+
+ rc = of_property_read_u32(of_node,
+ "qcom,default-topology-index", &top_sel);
+ if (rc) {
+ pr_err("no default topology selected, rc = %d\n", rc);
+ goto parse_fail;
+ }
+
+ if (top_sel >= top_count) {
+ rc = -EINVAL;
+ pr_err("default topology is specified is not valid, rc = %d\n",
+ rc);
+ goto parse_fail;
+ }
+
+ pr_info("default topology: lm: %d comp_enc:%d intf: %d\n",
+ topology[top_sel].num_lm,
+ topology[top_sel].num_enc,
+ topology[top_sel].num_intf);
+
+parse_done:
+ panel->mode.mode_info = kzalloc(sizeof(struct msm_mode_info),
+ GFP_KERNEL);
+ memcpy(&panel->mode.mode_info->topology, &topology[top_sel],
+ sizeof(struct msm_display_topology));
+parse_fail:
+ kfree(topology);
+read_fail:
+ kfree(array);
+
+ return rc;
+}
+
struct dsi_panel *dsi_panel_get(struct device *parent,
struct device_node *of_node)
{
@@ -2084,6 +2198,13 @@
panel->mode.pixel_clk_khz = (DSI_H_TOTAL(&panel->mode.timing) *
DSI_V_TOTAL(&panel->mode.timing) *
panel->mode.timing.refresh_rate) / 1000;
+
+ rc = dsi_panel_parse_topology(panel, of_node);
+ if (rc) {
+ pr_err("failed to parse panel topology, rc=%d\n", rc);
+ goto error;
+ }
+
rc = dsi_panel_parse_host_config(panel, of_node);
if (rc) {
pr_err("failed to parse host configuration, rc=%d\n", rc);
@@ -2153,6 +2274,8 @@
for (i = 0; i < DSI_CMD_SET_MAX; i++)
dsi_panel_destroy_cmd_packets(&panel->cmd_sets[i]);
+ kfree(panel->mode.mode_info);
+
/* TODO: more free */
kfree(panel);
}
@@ -2611,3 +2734,6 @@
mutex_unlock(&panel->panel_lock);
return rc;
}
+
+module_param_string(display_param, display_config, MAX_CMDLINE_PARAM_LEN, 0600);
+MODULE_PARM_DESC(display_param, "format: configx - x indexes the selected topology from the display topology list. Index 0 corresponds to the first topology in the list");
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 4471d0b..64e9544 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -164,6 +164,7 @@
/* enum/bitmask properties */
CONNECTOR_PROP_TOPOLOGY_NAME,
CONNECTOR_PROP_TOPOLOGY_CONTROL,
+ CONNECTOR_PROP_AUTOREFRESH,
/* total # of properties */
CONNECTOR_PROP_COUNT
@@ -353,6 +354,26 @@
};
/**
+ * struct msm_display_topology - defines a display topology pipeline
+ * @num_lm: number of layer mixers used
+ * @num_enc: number of compression encoder blocks used
+ * @num_intf: number of interfaces the panel is mounted on
+ */
+struct msm_display_topology {
+ u32 num_lm;
+ u32 num_enc;
+ u32 num_intf;
+};
+
+/**
+ * struct msm_mode_info - defines all msm custom mode info
+ * @topology - supported topology for the mode
+ */
+struct msm_mode_info {
+ struct msm_display_topology topology;
+};
+
+/**
* struct msm_display_info - defines display properties
* @intf_type: DRM_MODE_CONNECTOR_ display type
* @capabilities: Bitmask of display flags
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index e3f8261..9f8d7ee 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -21,6 +21,9 @@
#define BL_NODE_NAME_SIZE 32
+/* Autorefresh will occur after FRAME_CNT frames. Large values are unlikely */
+#define AUTOREFRESH_MAX_FRAME_CNT 6
+
#define SDE_DEBUG_CONN(c, fmt, ...) SDE_DEBUG("conn%d " fmt,\
(c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
@@ -990,6 +993,10 @@
msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
+ msm_property_install_range(&c_conn->property_info, "autorefresh",
+ 0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0,
+ CONNECTOR_PROP_AUTOREFRESH);
+
/* enum/bitmask properties */
msm_property_install_enum(&c_conn->property_info, "topology_name",
DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name,
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 601299e..c8c0eed 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -121,6 +121,17 @@
int (*get_info)(struct msm_display_info *info, void *display);
/**
+ * get_topology - retrieve current topology for the mode selected
+ * @drm_mode: Display mode set for the display
+ * @topology: Out parameter. Topology for the mode.
+ * @max_mixer_width: max width supported by HW layer mixer
+ * Returns: Zero on success
+ */
+ int (*get_topology)(const struct drm_display_mode *drm_mode,
+ struct msm_display_topology *topology,
+ u32 max_mixer_width);
+
+ /**
* enable_event - notify display of event registration/unregistration
* @connector: Pointer to drm connector structure
* @event_idx: SDE connector event index
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 6bae083..f2d78cb 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -808,6 +808,44 @@
return 0;
}
+static int _sde_crtc_check_autorefresh(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *crtc_state;
+ struct drm_connector *conn;
+ struct drm_connector_state *conn_state;
+ int i;
+
+ if (!crtc || !state)
+ return -EINVAL;
+
+ sde_crtc = to_sde_crtc(crtc);
+ crtc_state = to_sde_crtc_state(state);
+
+ if (sde_kms_rect_is_null(&crtc_state->crtc_roi))
+ return 0;
+
+ /* partial update active, check if autorefresh is also requested */
+ for_each_connector_in_state(state->state, conn, conn_state, i) {
+ uint64_t autorefresh;
+
+ if (!conn_state || conn_state->crtc != crtc)
+ continue;
+
+ autorefresh = sde_connector_get_property(conn_state,
+ CONNECTOR_PROP_AUTOREFRESH);
+ if (autorefresh) {
+ SDE_ERROR(
+ "%s: autorefresh & partial crtc roi incompatible %llu\n",
+ sde_crtc->name, autorefresh);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int _sde_crtc_set_lm_roi(struct drm_crtc *crtc,
struct drm_crtc_state *state, int lm_idx)
{
@@ -953,6 +991,10 @@
if (rc)
return rc;
+ rc = _sde_crtc_check_autorefresh(crtc, state);
+ if (rc)
+ return rc;
+
for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) {
rc = _sde_crtc_set_lm_roi(crtc, state, lm_idx);
if (rc)
@@ -2074,6 +2116,33 @@
crtc->state = &cstate->base;
}
+static int _sde_crtc_vblank_no_lock(struct sde_crtc *sde_crtc, bool en)
+{
+ if (!sde_crtc) {
+ SDE_ERROR("invalid crtc\n");
+ return -EINVAL;
+ } else if (en && atomic_inc_return(&sde_crtc->vblank_refcount) == 1) {
+ SDE_DEBUG("crtc%d vblank enable\n", sde_crtc->base.base.id);
+ if (!sde_crtc->suspend)
+ _sde_crtc_vblank_enable_nolock(sde_crtc, true);
+ } else if (!en && atomic_read(&sde_crtc->vblank_refcount) < 1) {
+ SDE_ERROR("crtc%d invalid vblank disable\n",
+ sde_crtc->base.base.id);
+ return -EINVAL;
+ } else if (!en && atomic_dec_return(&sde_crtc->vblank_refcount) == 0) {
+ SDE_DEBUG("crtc%d vblank disable\n", sde_crtc->base.base.id);
+ if (!sde_crtc->suspend)
+ _sde_crtc_vblank_enable_nolock(sde_crtc, false);
+ } else {
+ SDE_DEBUG("crtc%d vblank %s refcount:%d\n",
+ sde_crtc->base.base.id,
+ en ? "enable" : "disable",
+ atomic_read(&sde_crtc->vblank_refcount));
+ }
+
+ return 0;
+}
+
static void sde_crtc_disable(struct drm_crtc *crtc)
{
struct sde_crtc *sde_crtc;
@@ -2103,13 +2172,9 @@
crtc->base.id);
SDE_EVT32(DRMID(crtc), atomic_read(&sde_crtc->vblank_refcount),
SDE_EVTLOG_FUNC_CASE1);
- drm_for_each_encoder(encoder, crtc->dev) {
- if (encoder->crtc != crtc)
- continue;
- sde_encoder_register_vblank_callback(encoder, NULL,
- NULL);
- }
- atomic_set(&sde_crtc->vblank_refcount, 0);
+ while (atomic_read(&sde_crtc->vblank_refcount))
+ if (_sde_crtc_vblank_no_lock(sde_crtc, false))
+ break;
}
if (atomic_read(&sde_crtc->frame_pending)) {
@@ -2463,7 +2528,7 @@
int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
{
struct sde_crtc *sde_crtc;
- int rc = 0;
+ int rc;
if (!crtc) {
SDE_ERROR("invalid crtc\n");
@@ -2472,25 +2537,9 @@
sde_crtc = to_sde_crtc(crtc);
mutex_lock(&sde_crtc->crtc_lock);
- if (en && atomic_inc_return(&sde_crtc->vblank_refcount) == 1) {
- SDE_DEBUG("crtc%d vblank enable\n", crtc->base.id);
- if (!sde_crtc->suspend)
- _sde_crtc_vblank_enable_nolock(sde_crtc, true);
- } else if (!en && atomic_read(&sde_crtc->vblank_refcount) < 1) {
- SDE_ERROR("crtc%d invalid vblank disable\n", crtc->base.id);
- rc = -EINVAL;
- } else if (!en && atomic_dec_return(&sde_crtc->vblank_refcount) == 0) {
- SDE_DEBUG("crtc%d vblank disable\n", crtc->base.id);
- if (!sde_crtc->suspend)
- _sde_crtc_vblank_enable_nolock(sde_crtc, false);
- } else {
- SDE_DEBUG("crtc%d vblank %s refcount:%d\n",
- crtc->base.id,
- en ? "enable" : "disable",
- atomic_read(&sde_crtc->vblank_refcount));
- }
-
+ rc = _sde_crtc_vblank_no_lock(sde_crtc, en);
mutex_unlock(&sde_crtc->crtc_lock);
+
return rc;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 7ad0955..98ba711 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -316,6 +316,21 @@
}
/**
+ * sde_crtc_frame_pending - retun the number of pending frames
+ * @crtc: Pointer to drm crtc object
+ */
+static inline int sde_crtc_frame_pending(struct drm_crtc *crtc)
+{
+ struct sde_crtc *sde_crtc;
+
+ if (!crtc)
+ return -EINVAL;
+
+ sde_crtc = to_sde_crtc(crtc);
+ return atomic_read(&sde_crtc->frame_pending);
+}
+
+/**
* sde_crtc_vblank - enable or disable vblanks for this crtc
* @crtc: Pointer to drm crtc object
* @en: true to enable vblanks, false to disable
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 94420ed..3357642 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -34,6 +34,7 @@
#include "sde_encoder_phys.h"
#include "sde_power_handle.h"
#include "sde_hw_dsc.h"
+#include "sde_crtc.h"
#define SDE_DEBUG_ENC(e, fmt, ...) SDE_DEBUG("enc%d " fmt,\
(e) ? (e)->base.base.id : -1, ##__VA_ARGS__)
@@ -58,6 +59,56 @@
#define MISR_BUFF_SIZE 256
+#define IDLE_TIMEOUT 64
+
+/**
+ * enum sde_enc_rc_events - events for resource control state machine
+ * @SDE_ENC_RC_EVENT_KICKOFF:
+ * This event happens at NORMAL priority.
+ * Event that signals the start of the transfer. When this event is
+ * received, enable MDP/DSI core clocks and request RSC with CMD state.
+ * Regardless of the previous state, the resource should be in ON state
+ * at the end of this event.
+ * @SDE_ENC_RC_EVENT_FRAME_DONE:
+ * This event happens at INTERRUPT level.
+ * Event signals the end of the data transfer after the PP FRAME_DONE
+ * event. At the end of this event, a delayed work is scheduled to go to
+ * IDLE_PC state after IDLE_TIMEOUT time.
+ * @SDE_ENC_RC_EVENT_STOP:
+ * This event happens at NORMAL priority.
+ * When this event is received, disable all the MDP/DSI core clocks
+ * and request RSC with IDLE state. Resource state should be in OFF
+ * at the end of the event.
+ * @SDE_ENC_RC_EARLY_WAKEUP
+ * This event happens at NORMAL priority from a work item.
+ * Event signals that there will be frame update soon and the driver should
+ * wake up early to update the frame with minimum latency.
+ * @SDE_ENC_RC_EVENT_ENTER_IDLE:
+ * This event happens at NORMAL priority from a work item.
+ * Event signals that there were no frame updates for IDLE_TIMEOUT time.
+ * This would disable MDP/DSI core clocks and request RSC with IDLE state
+ * and change the resource state to IDLE.
+ */
+enum sde_enc_rc_events {
+ SDE_ENC_RC_EVENT_KICKOFF = 1,
+ SDE_ENC_RC_EVENT_FRAME_DONE,
+ SDE_ENC_RC_EVENT_STOP,
+ SDE_ENC_RC_EVENT_EARLY_WAKE_UP,
+ SDE_ENC_RC_EVENT_ENTER_IDLE
+};
+
+/*
+ * enum sde_enc_rc_states - states that the resource control maintains
+ * @SDE_ENC_RC_STATE_OFF: Resource is in OFF state
+ * @SDE_ENC_RC_STATE_ON: Resource is in ON state
+ * @SDE_ENC_RC_STATE_IDLE: Resource is in IDLE state
+ */
+enum sde_enc_rc_states {
+ SDE_ENC_RC_STATE_OFF,
+ SDE_ENC_RC_STATE_ON,
+ SDE_ENC_RC_STATE_IDLE
+};
+
/**
* struct sde_encoder_virt - virtual encoder. Container of one or more physical
* encoders. Virtual encoder manages one "logical" display. Physical
@@ -91,7 +142,16 @@
* @crtc_frame_event: callback event
* @frame_done_timeout: frame done timeout in Hz
* @frame_done_timer: watchdog timer for frame done event
+ * @rsc_client: rsc client pointer
+ * @rsc_state_init: boolean to indicate rsc config init
+ * @disp_info: local copy of msm_display_info struct
* @misr_enable: misr enable/disable status
+ * @idle_pc_supported: indicate if idle power collaps is supported
+ * @rc_lock: resource control mutex lock to protect
+ * virt encoder over various state changes
+ * @rc_state: resource controller state
+ * @delayed_off_work: delayed worker to schedule disabling of
+ * clks and resources after IDLE_TIMEOUT time.
*/
struct sde_encoder_virt {
struct drm_encoder base;
@@ -120,9 +180,14 @@
struct timer_list frame_done_timer;
struct sde_rsc_client *rsc_client;
+ bool rsc_state_init;
struct msm_display_info disp_info;
- bool rsc_state_update;
bool misr_enable;
+
+ bool idle_pc_supported;
+ struct mutex rc_lock;
+ enum sde_enc_rc_states rc_state;
+ struct delayed_work delayed_off_work;
};
#define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base)
@@ -700,6 +765,11 @@
sde_enc = to_sde_encoder_virt(drm_enc);
disp_info = &sde_enc->disp_info;
+ if (!sde_enc->rsc_client) {
+ SDE_DEBUG("rsc client not created\n");
+ return 0;
+ }
+
/**
* only primary command mode panel can request CMD state.
* all other panels/displays can request for VID state including
@@ -710,14 +780,14 @@
disp_info->is_primary) ? SDE_RSC_CMD_STATE :
SDE_RSC_VID_STATE) : SDE_RSC_IDLE_STATE;
- if (rsc_state != SDE_RSC_IDLE_STATE && !sde_enc->rsc_state_update
+ if (rsc_state != SDE_RSC_IDLE_STATE && !sde_enc->rsc_state_init
&& disp_info->is_primary) {
rsc_config.fps = disp_info->frame_rate;
rsc_config.vtotal = disp_info->vtotal;
rsc_config.prefill_lines = disp_info->prefill_lines;
rsc_config.jitter = disp_info->jitter;
/* update it only once */
- sde_enc->rsc_state_update = true;
+ sde_enc->rsc_state_init = true;
ret = sde_rsc_client_state_update(sde_enc->rsc_client,
rsc_state, &rsc_config,
@@ -748,6 +818,277 @@
return disp_info->is_primary ? sde_enc->rsc_client : NULL;
}
+static void _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,
+ bool enable)
+{
+ struct msm_drm_private *priv;
+ struct sde_kms *sde_kms;
+ struct sde_encoder_virt *sde_enc;
+ int i;
+
+ sde_enc = to_sde_encoder_virt(drm_enc);
+ priv = drm_enc->dev->dev_private;
+ sde_kms = to_sde_kms(priv->kms);
+
+ SDE_DEBUG_ENC(sde_enc, "enable:%d\n", enable);
+ SDE_EVT32(DRMID(drm_enc), enable);
+
+ if (!sde_enc->cur_master) {
+ SDE_ERROR("encoder master not set\n");
+ return;
+ }
+
+ if (enable) {
+ /* enable SDE core clks */
+ sde_power_resource_enable(&priv->phandle,
+ sde_kms->core_client, true);
+
+ /* enable DSI clks */
+ sde_connector_clk_ctrl(sde_enc->cur_master->connector, true);
+
+ /* enable all the irq */
+ for (i = 0; i < sde_enc->num_phys_encs; i++) {
+ struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
+
+ if (phys && phys->ops.irq_control)
+ phys->ops.irq_control(phys, true);
+ }
+
+ /* enable RSC */
+ sde_encoder_update_rsc_client(drm_enc, true);
+
+ } else {
+
+ /* disable RSC */
+ sde_encoder_update_rsc_client(drm_enc, false);
+
+ /* disable all the irq */
+ for (i = 0; i < sde_enc->num_phys_encs; i++) {
+ struct sde_encoder_phys *phys =
+ sde_enc->phys_encs[i];
+
+ if (phys && phys->ops.irq_control)
+ phys->ops.irq_control(phys, false);
+ }
+
+ /* disable DSI clks */
+ sde_connector_clk_ctrl(sde_enc->cur_master->connector, false);
+
+ /* disable SDE core clks */
+ sde_power_resource_enable(&priv->phandle,
+ sde_kms->core_client, false);
+ }
+
+}
+
+static int sde_encoder_resource_control(struct drm_encoder *drm_enc,
+ u32 sw_event)
+{
+ bool schedule_off = false;
+ struct sde_encoder_virt *sde_enc;
+
+ if (!drm_enc || !drm_enc->dev || !drm_enc->dev->dev_private) {
+ SDE_ERROR("invalid parameters\n");
+ return -EINVAL;
+ }
+ sde_enc = to_sde_encoder_virt(drm_enc);
+
+ /*
+ * when idle_pc is not supported, process only KICKOFF and STOP
+ * event and return early for other events (ie video mode).
+ */
+ if (!sde_enc->idle_pc_supported &&
+ (sw_event != SDE_ENC_RC_EVENT_KICKOFF &&
+ sw_event != SDE_ENC_RC_EVENT_STOP))
+ return 0;
+
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, idle_pc_supported:%d\n", sw_event,
+ sde_enc->idle_pc_supported);
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
+ sde_enc->rc_state, SDE_EVTLOG_FUNC_ENTRY);
+
+ switch (sw_event) {
+ case SDE_ENC_RC_EVENT_KICKOFF:
+ /* cancel delayed off work, if any */
+ if (cancel_delayed_work_sync(&sde_enc->delayed_off_work))
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work cancelled\n",
+ sw_event);
+
+ mutex_lock(&sde_enc->rc_lock);
+
+ /* return if the resource control is already in ON state */
+ if (sde_enc->rc_state == SDE_ENC_RC_STATE_ON) {
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc in ON state\n",
+ sw_event);
+ mutex_unlock(&sde_enc->rc_lock);
+ return 0;
+ }
+
+ /* enable all the clks and resources */
+ _sde_encoder_resource_control_helper(drm_enc, true);
+
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+ SDE_ENC_RC_STATE_ON, SDE_EVTLOG_FUNC_CASE1);
+ sde_enc->rc_state = SDE_ENC_RC_STATE_ON;
+
+ mutex_unlock(&sde_enc->rc_lock);
+ break;
+
+ case SDE_ENC_RC_EVENT_FRAME_DONE:
+ /*
+ * mutex lock is not used as this event happens at interrupt
+ * context. And locking is not required as, the other events
+ * like KICKOFF and STOP does a wait-for-idle before executing
+ * the resource_control
+ */
+ if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) {
+ SDE_ERROR_ENC(sde_enc, "sw_event:%d,rc:%d-unexpected\n",
+ sw_event, sde_enc->rc_state);
+ return -EINVAL;
+ }
+
+ /*
+ * schedule off work item only when there are no
+ * frames pending
+ */
+ if (sde_crtc_frame_pending(drm_enc->crtc) > 1) {
+ SDE_DEBUG_ENC(sde_enc, "skip schedule work");
+ return 0;
+ }
+
+ /* schedule delayed off work */
+ schedule_delayed_work(&sde_enc->delayed_off_work,
+ msecs_to_jiffies(IDLE_TIMEOUT));
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+ SDE_EVTLOG_FUNC_CASE2);
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work scheduled\n",
+ sw_event);
+ break;
+
+ case SDE_ENC_RC_EVENT_STOP:
+ /* cancel delayed off work, if any */
+ if (cancel_delayed_work_sync(&sde_enc->delayed_off_work))
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work cancelled\n",
+ sw_event);
+
+ mutex_lock(&sde_enc->rc_lock);
+
+ /* return if the resource control is already in OFF state */
+ if (sde_enc->rc_state == SDE_ENC_RC_STATE_OFF) {
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc in OFF state\n",
+ sw_event);
+ mutex_unlock(&sde_enc->rc_lock);
+ return 0;
+ }
+
+ /*
+ * disable the clks and resources only if the resource control
+ * is in ON state, otherwise the clks and resources would have
+ * been disabled while going into IDLE state
+ */
+ if (sde_enc->rc_state == SDE_ENC_RC_STATE_ON)
+ _sde_encoder_resource_control_helper(drm_enc, false);
+
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+ SDE_ENC_RC_STATE_OFF, SDE_EVTLOG_FUNC_CASE3);
+ sde_enc->rc_state = SDE_ENC_RC_STATE_OFF;
+
+ mutex_unlock(&sde_enc->rc_lock);
+ break;
+
+ case SDE_ENC_RC_EVENT_EARLY_WAKE_UP:
+ /* cancel delayed off work, if any */
+ if (cancel_delayed_work_sync(&sde_enc->delayed_off_work)) {
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work cancelled\n",
+ sw_event);
+ schedule_off = true;
+ }
+
+ mutex_lock(&sde_enc->rc_lock);
+
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+ schedule_off, SDE_EVTLOG_FUNC_CASE4);
+
+ /* return if the resource control is in OFF state */
+ if (sde_enc->rc_state == SDE_ENC_RC_STATE_OFF) {
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc in OFF state\n",
+ sw_event);
+ mutex_unlock(&sde_enc->rc_lock);
+ return 0;
+ }
+
+ /*
+ * enable all the clks and resources if resource control is
+ * coming out of IDLE state
+ */
+ if (sde_enc->rc_state == SDE_ENC_RC_STATE_IDLE) {
+ _sde_encoder_resource_control_helper(drm_enc, true);
+ sde_enc->rc_state = SDE_ENC_RC_STATE_ON;
+ schedule_off = true;
+ }
+
+ /*
+ * schedule off work when there are no frames pending and
+ * 1. early wakeup cancelled off work
+ * 2. early wakeup changed the rc_state to ON - this is to
+ * handle cases where early wakeup is called but no
+ * frame updates
+ */
+ if (schedule_off && !sde_crtc_frame_pending(drm_enc->crtc)) {
+ /* schedule delayed off work */
+ schedule_delayed_work(&sde_enc->delayed_off_work,
+ msecs_to_jiffies(IDLE_TIMEOUT));
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work scheduled\n",
+ sw_event);
+ }
+
+ mutex_unlock(&sde_enc->rc_lock);
+ break;
+
+ case SDE_ENC_RC_EVENT_ENTER_IDLE:
+ mutex_lock(&sde_enc->rc_lock);
+
+ if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) {
+ SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc:%d !ON state\n",
+ sw_event, sde_enc->rc_state);
+ mutex_unlock(&sde_enc->rc_lock);
+ return 0;
+ }
+
+ /* disable all the clks and resources */
+ _sde_encoder_resource_control_helper(drm_enc, false);
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
+ SDE_ENC_RC_STATE_IDLE, SDE_EVTLOG_FUNC_CASE5);
+ sde_enc->rc_state = SDE_ENC_RC_STATE_IDLE;
+
+ mutex_unlock(&sde_enc->rc_lock);
+ break;
+
+ default:
+ SDE_ERROR("unexpected sw_event: %d\n", sw_event);
+ break;
+ }
+
+ SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
+ sde_enc->rc_state, SDE_EVTLOG_FUNC_EXIT);
+ return 0;
+}
+
+static void sde_encoder_off_work(struct work_struct *work)
+{
+ struct delayed_work *dw = to_delayed_work(work);
+ struct sde_encoder_virt *sde_enc = container_of(dw,
+ struct sde_encoder_virt, delayed_off_work);
+
+ if (!sde_enc) {
+ SDE_ERROR("invalid sde encoder\n");
+ return;
+ }
+
+ sde_encoder_resource_control(&sde_enc->base,
+ SDE_ENC_RC_EVENT_ENTER_IDLE);
+}
+
static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
struct drm_display_mode *mode,
struct drm_display_mode *adj_mode)
@@ -859,31 +1200,37 @@
SDE_DEBUG_ENC(sde_enc, "\n");
SDE_EVT32(DRMID(drm_enc));
- ret = _sde_encoder_power_enable(sde_enc, true);
- if (ret)
- return;
-
sde_enc->cur_master = NULL;
+ for (i = 0; i < sde_enc->num_phys_encs; i++) {
+ struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
+
+ if (phys && phys->ops.is_master && phys->ops.is_master(phys)) {
+ SDE_DEBUG_ENC(sde_enc, "master is now idx %d\n", i);
+ sde_enc->cur_master = phys;
+ break;
+ }
+ }
+
+ if (!sde_enc->cur_master) {
+ SDE_ERROR("virt encoder has no master! num_phys %d\n", i);
+ return;
+ }
+
+ ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF);
+ if (ret) {
+ SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n",
+ ret);
+ return;
+ }
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
- if (phys) {
- if (phys->ops.is_master && phys->ops.is_master(phys)) {
- SDE_DEBUG_ENC(sde_enc,
- "master is now idx %d\n", i);
- sde_enc->cur_master = phys;
- } else if (phys->ops.enable) {
- phys->ops.enable(phys);
- }
- }
+ if (phys && (phys != sde_enc->cur_master) && phys->ops.enable)
+ phys->ops.enable(phys);
}
- sde_encoder_update_rsc_client(drm_enc, true);
-
- if (!sde_enc->cur_master)
- SDE_ERROR("virt encoder has no master! num_phys %d\n", i);
- else if (sde_enc->cur_master->ops.enable)
+ if (sde_enc->cur_master && sde_enc->cur_master->ops.enable)
sde_enc->cur_master->ops.enable(sde_enc->cur_master);
if (sde_enc->cur_master && sde_enc->cur_master->hw_mdptop &&
@@ -929,9 +1276,8 @@
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
- if (phys) {
- if (phys->ops.disable && !phys->ops.is_master(phys))
- phys->ops.disable(phys);
+ if (phys && phys->ops.disable && !phys->ops.is_master(phys)) {
+ phys->ops.disable(phys);
phys->connector = NULL;
}
}
@@ -942,17 +1288,19 @@
del_timer_sync(&sde_enc->frame_done_timer);
}
- sde_encoder_update_rsc_client(drm_enc, false);
-
if (sde_enc->cur_master && sde_enc->cur_master->ops.disable)
sde_enc->cur_master->ops.disable(sde_enc->cur_master);
- sde_enc->cur_master = NULL;
- SDE_DEBUG_ENC(sde_enc, "cleared master\n");
+ sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_STOP);
+
+ if (sde_enc->cur_master) {
+ sde_enc->cur_master->connector = NULL;
+ sde_enc->cur_master = NULL;
+ }
+
+ SDE_DEBUG_ENC(sde_enc, "encoder disabled\n");
sde_rm_release(&sde_kms->rm, drm_enc);
-
- _sde_encoder_power_enable(sde_enc, false);
}
static enum sde_intf sde_encoder_get_intf(struct sde_mdss_cfg *catalog,
@@ -1081,6 +1429,9 @@
atomic_set(&sde_enc->frame_done_timeout, 0);
del_timer(&sde_enc->frame_done_timer);
+ sde_encoder_resource_control(drm_enc,
+ SDE_ENC_RC_EVENT_FRAME_DONE);
+
if (sde_enc->crtc_frame_event_cb)
sde_enc->crtc_frame_event_cb(
sde_enc->crtc_frame_event_cb_data,
@@ -1323,6 +1674,8 @@
}
}
+ sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF);
+
/* if any phys needs reset, reset all phys, in-order */
if (needs_hw_reset) {
for (i = 0; i < sde_enc->num_phys_encs; i++) {
@@ -1813,6 +2166,9 @@
phys_params.comp_type = disp_info->comp_info.comp_type;
+ if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE)
+ sde_enc->idle_pc_supported = sde_kms->catalog->has_idle_pc;
+
mutex_lock(&sde_enc->enc_lock);
for (i = 0; i < disp_info->num_of_h_tiles && !ret; i++) {
/*
@@ -1973,6 +2329,9 @@
sde_enc->rsc_client = NULL;
}
+ mutex_init(&sde_enc->rc_lock);
+ INIT_DELAYED_WORK(&sde_enc->delayed_off_work, sde_encoder_off_work);
+
memcpy(&sde_enc->disp_info, disp_info, sizeof(*disp_info));
SDE_DEBUG_ENC(sde_enc, "created\n");
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index da155b0..6942292 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -117,6 +117,7 @@
* @collect_misr: Collects MISR data on frame update
* @hw_reset: Issue HW recovery such as CTL reset and clear
* SDE_ENC_ERR_NEEDS_HW_RESET state
+ * @irq_control: Handler to enable/disable all the encoder IRQs
*/
struct sde_encoder_phys_ops {
@@ -150,6 +151,7 @@
bool enable, u32 frame_count);
u32 (*collect_misr)(struct sde_encoder_phys *phys_enc);
void (*hw_reset)(struct sde_encoder_phys *phys_enc);
+ void (*irq_control)(struct sde_encoder_phys *phys, bool enable);
};
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index 5b59828..a4f40f2 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -363,6 +363,78 @@
return 0;
}
+static int sde_encoder_phys_cmd_control_vblank_irq(
+ struct sde_encoder_phys *phys_enc,
+ bool enable)
+{
+ struct sde_encoder_phys_cmd *cmd_enc =
+ to_sde_encoder_phys_cmd(phys_enc);
+ int ret = 0;
+
+ if (!phys_enc) {
+ SDE_ERROR("invalid encoder\n");
+ return -EINVAL;
+ }
+
+ /* Slave encoders don't report vblank */
+ if (!sde_encoder_phys_cmd_is_master(phys_enc))
+ goto end;
+
+ SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n",
+ __builtin_return_address(0),
+ enable, atomic_read(&phys_enc->vblank_refcount));
+
+ SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
+ enable, atomic_read(&phys_enc->vblank_refcount));
+
+ if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
+ ret = sde_encoder_phys_cmd_register_irq(phys_enc,
+ SDE_IRQ_TYPE_PING_PONG_RD_PTR,
+ INTR_IDX_RDPTR,
+ sde_encoder_phys_cmd_pp_rd_ptr_irq,
+ "pp_rd_ptr");
+ else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
+ ret = sde_encoder_phys_cmd_unregister_irq(phys_enc,
+ INTR_IDX_RDPTR);
+
+end:
+ if (ret)
+ SDE_ERROR_CMDENC(cmd_enc,
+ "control vblank irq error %d, enable %d\n",
+ ret, enable);
+
+ return ret;
+}
+
+void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
+ bool enable)
+{
+ if (!phys_enc || _sde_encoder_phys_is_ppsplit_slave(phys_enc))
+ return;
+
+ if (enable) {
+ sde_encoder_phys_cmd_register_irq(phys_enc,
+ SDE_IRQ_TYPE_PING_PONG_COMP,
+ INTR_IDX_PINGPONG,
+ sde_encoder_phys_cmd_pp_tx_done_irq,
+ "pp_tx_done");
+
+ sde_encoder_phys_cmd_control_vblank_irq(phys_enc, true);
+
+ sde_encoder_phys_cmd_register_irq(phys_enc,
+ SDE_IRQ_TYPE_INTF_UNDER_RUN,
+ INTR_IDX_UNDERRUN,
+ sde_encoder_phys_cmd_underrun_irq,
+ "underrun");
+ } else {
+ sde_encoder_phys_cmd_unregister_irq(
+ phys_enc, INTR_IDX_UNDERRUN);
+ sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
+ sde_encoder_phys_cmd_unregister_irq(
+ phys_enc, INTR_IDX_PINGPONG);
+ }
+}
+
static void sde_encoder_phys_cmd_tearcheck_config(
struct sde_encoder_phys *phys_enc)
{
@@ -477,56 +549,12 @@
return _sde_encoder_phys_is_ppsplit(phys_enc);
}
-static int sde_encoder_phys_cmd_control_vblank_irq(
- struct sde_encoder_phys *phys_enc,
- bool enable)
-{
- struct sde_encoder_phys_cmd *cmd_enc =
- to_sde_encoder_phys_cmd(phys_enc);
- int ret = 0;
-
- if (!phys_enc) {
- SDE_ERROR("invalid encoder\n");
- return -EINVAL;
- }
-
- /* Slave encoders don't report vblank */
- if (!sde_encoder_phys_cmd_is_master(phys_enc))
- goto end;
-
- SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n",
- __builtin_return_address(0),
- enable, atomic_read(&phys_enc->vblank_refcount));
-
- SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
- enable, atomic_read(&phys_enc->vblank_refcount));
-
- if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
- ret = sde_encoder_phys_cmd_register_irq(phys_enc,
- SDE_IRQ_TYPE_PING_PONG_RD_PTR,
- INTR_IDX_RDPTR,
- sde_encoder_phys_cmd_pp_rd_ptr_irq,
- "pp_rd_ptr");
- else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
- ret = sde_encoder_phys_cmd_unregister_irq(phys_enc,
- INTR_IDX_RDPTR);
-
-end:
- if (ret)
- SDE_ERROR_CMDENC(cmd_enc,
- "control vblank irq error %d, enable %d\n",
- ret, enable);
-
- return ret;
-}
-
static void sde_encoder_phys_cmd_enable(struct sde_encoder_phys *phys_enc)
{
struct sde_encoder_phys_cmd *cmd_enc =
to_sde_encoder_phys_cmd(phys_enc);
struct sde_hw_ctl *ctl;
u32 flush_mask = 0;
- int ret;
if (!phys_enc || !phys_enc->hw_ctl) {
SDE_ERROR("invalid arg(s), encoder %d\n", phys_enc != 0);
@@ -543,38 +571,6 @@
sde_encoder_phys_cmd_pingpong_config(phys_enc);
- if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
- goto update_flush;
-
- /* Both master and slave need to register for pp_tx_done */
- ret = sde_encoder_phys_cmd_register_irq(phys_enc,
- SDE_IRQ_TYPE_PING_PONG_COMP,
- INTR_IDX_PINGPONG,
- sde_encoder_phys_cmd_pp_tx_done_irq,
- "pp_tx_done");
- if (ret)
- return;
-
- ret = sde_encoder_phys_cmd_control_vblank_irq(phys_enc, true);
- if (ret) {
- sde_encoder_phys_cmd_unregister_irq(phys_enc,
- INTR_IDX_PINGPONG);
- return;
- }
-
- ret = sde_encoder_phys_cmd_register_irq(phys_enc,
- SDE_IRQ_TYPE_INTF_UNDER_RUN,
- INTR_IDX_UNDERRUN,
- sde_encoder_phys_cmd_underrun_irq,
- "underrun");
- if (ret) {
- sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
- sde_encoder_phys_cmd_unregister_irq(phys_enc,
- INTR_IDX_PINGPONG);
- return;
- }
-
-update_flush:
ctl = phys_enc->hw_ctl;
ctl->ops.get_bitmask_intf(ctl, &flush_mask, cmd_enc->intf_idx);
ctl->ops.update_pending_flush(ctl, flush_mask);
@@ -613,21 +609,9 @@
SDE_EVT32(DRMID(phys_enc->parent),
phys_enc->hw_pp->idx - PINGPONG_0, ret);
}
-
- sde_encoder_phys_cmd_unregister_irq(
- phys_enc, INTR_IDX_UNDERRUN);
- sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
- sde_encoder_phys_cmd_unregister_irq(
- phys_enc, INTR_IDX_PINGPONG);
}
phys_enc->enable_state = SDE_ENC_DISABLED;
-
- if (atomic_read(&phys_enc->vblank_refcount))
- SDE_ERROR("enc:%d role:%d invalid vblank refcount %d\n",
- phys_enc->parent->base.id,
- phys_enc->split_role,
- atomic_read(&phys_enc->vblank_refcount));
}
static void sde_encoder_phys_cmd_destroy(struct sde_encoder_phys *phys_enc)
@@ -723,6 +707,7 @@
ops->trigger_start = sde_encoder_helper_trigger_start;
ops->needs_single_flush = sde_encoder_phys_cmd_needs_single_flush;
ops->hw_reset = sde_encoder_helper_hw_reset;
+ ops->irq_control = sde_encoder_phys_cmd_irq_control;
}
struct sde_encoder_phys *sde_encoder_phys_cmd_init(
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index df099d3..5cb84b4 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -391,10 +391,24 @@
phys_enc);
}
+static bool _sde_encoder_phys_is_ppsplit(struct sde_encoder_phys *phys_enc)
+{
+ enum sde_rm_topology_name topology;
+
+ if (!phys_enc)
+ return false;
+
+ topology = sde_connector_get_topology_name(phys_enc->connector);
+ if (topology == SDE_RM_TOPOLOGY_PPSPLIT)
+ return true;
+
+ return false;
+}
+
static bool sde_encoder_phys_vid_needs_single_flush(
struct sde_encoder_phys *phys_enc)
{
- return phys_enc && phys_enc->split_role != ENC_ROLE_SOLO;
+ return phys_enc && _sde_encoder_phys_is_ppsplit(phys_enc);
}
static int sde_encoder_phys_vid_register_irq(struct sde_encoder_phys *phys_enc,
@@ -680,7 +694,7 @@
KICKOFF_TIMEOUT_MS);
if (ret <= 0) {
irq_status = sde_core_irq_read(phys_enc->sde_kms,
- INTR_IDX_VSYNC, true);
+ vid_enc->irq_idx[INTR_IDX_VSYNC], true);
if (irq_status) {
SDE_EVT32(DRMID(phys_enc->parent),
vid_enc->hw_intf->idx - INTF_0);
diff --git a/drivers/gpu/drm/msm/sde/sde_fence.c b/drivers/gpu/drm/msm/sde/sde_fence.c
index 46823b6..5f257bb 100644
--- a/drivers/gpu/drm/msm/sde/sde_fence.c
+++ b/drivers/gpu/drm/msm/sde/sde_fence.c
@@ -16,6 +16,8 @@
#include "sde_kms.h"
#include "sde_fence.h"
+#define TIMELINE_VAL_LENGTH 128
+
void *sde_sync_get(uint64_t fd)
{
/* force signed compare, fdget accepts an int argument */
@@ -31,14 +33,31 @@
signed long sde_sync_wait(void *fnc, long timeout_ms)
{
struct fence *fence = fnc;
+ int rc;
+ char timeline_str[TIMELINE_VAL_LENGTH];
if (!fence)
return -EINVAL;
else if (fence_is_signaled(fence))
return timeout_ms ? msecs_to_jiffies(timeout_ms) : 1;
- return fence_wait_timeout(fence, true,
+ rc = fence_wait_timeout(fence, true,
msecs_to_jiffies(timeout_ms));
+ if (!rc || (rc == -EINVAL)) {
+ if (fence->ops->timeline_value_str)
+ fence->ops->timeline_value_str(fence,
+ timeline_str, TIMELINE_VAL_LENGTH);
+
+ SDE_ERROR(
+ "fence driver name:%s timeline name:%s seqno:0x%x timeline:%s signaled:0x%x\n",
+ fence->ops->get_driver_name(fence),
+ fence->ops->get_timeline_name(fence),
+ fence->seqno, timeline_str,
+ fence->ops->signaled ?
+ fence->ops->signaled(fence) : 0xffffffff);
+ }
+
+ return rc;
}
uint32_t sde_sync_get_name_prefix(void *fence)
diff --git a/drivers/gpu/drm/msm/sde/sde_formats.c b/drivers/gpu/drm/msm/sde/sde_formats.c
index e7f3df7..c3477b5 100644
--- a/drivers/gpu/drm/msm/sde/sde_formats.c
+++ b/drivers/gpu/drm/msm/sde/sde_formats.c
@@ -1072,7 +1072,8 @@
DRM_ERROR("invalid handle for plane %d\n", i);
return -EINVAL;
}
- bos_total_size += bos[i]->size;
+ if ((i == 0) || (bos[i] != bos[0]))
+ bos_total_size += bos[i]->size;
}
if (bos_total_size < layout.total_size) {
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index cfa3b5e..b8ab066 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -120,6 +120,7 @@
SRC_SPLIT,
DIM_LAYER,
SMART_DMA_REV,
+ IDLE_PC,
SDE_PROP_MAX,
};
@@ -313,6 +314,7 @@
{SRC_SPLIT, "qcom,sde-has-src-split", false, PROP_TYPE_BOOL},
{DIM_LAYER, "qcom,sde-has-dim-layer", false, PROP_TYPE_BOOL},
{SMART_DMA_REV, "qcom,sde-smart-dma-rev", false, PROP_TYPE_STRING},
+ {IDLE_PC, "qcom,sde-has-idle-pc", false, PROP_TYPE_BOOL},
};
static struct sde_prop_type sde_perf_prop[] = {
@@ -2214,6 +2216,7 @@
cfg->has_src_split = PROP_VALUE_ACCESS(prop_value, SRC_SPLIT, 0);
cfg->has_dim_layer = PROP_VALUE_ACCESS(prop_value, DIM_LAYER, 0);
+ cfg->has_idle_pc = PROP_VALUE_ACCESS(prop_value, IDLE_PC, 0);
end:
kfree(prop_value);
return rc;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 97da08f..b5f83ad 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -713,6 +713,7 @@
* @ubwc_version UBWC feature version (0x0 for not supported)
* @has_sbuf indicate if stream buffer is available
* @sbuf_headroom stream buffer headroom in lines
+ * @has_idle_pc indicate if idle power collapse feature is supported
* @dma_formats Supported formats for dma pipe
* @cursor_formats Supported formats for cursor pipe
* @vig_formats Supported formats for vig pipe
@@ -735,6 +736,7 @@
u32 ubwc_version;
bool has_sbuf;
u32 sbuf_headroom;
+ bool has_idle_pc;
u32 mdss_count;
struct sde_mdss_base_cfg mdss[MAX_BLOCKS];
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c b/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
index f1b9c32..8df4de2 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
@@ -25,6 +25,9 @@
{
int i;
+ if (!m || !addr || !b)
+ return ERR_PTR(-EINVAL);
+
for (i = 0; i < m->dspp_count; i++) {
if (dspp == m->dspp[i].id) {
b->base_off = addr;
@@ -43,6 +46,9 @@
{
int i = 0, ret;
+ if (!c || !c->cap || !c->cap->sblk)
+ return;
+
for (i = 0; i < SDE_DSPP_MAX; i++) {
if (!test_bit(i, &features))
continue;
@@ -119,6 +125,9 @@
struct sde_hw_dspp *c;
struct sde_dspp_cfg *cfg;
+ if (!addr || !m)
+ return ERR_PTR(-EINVAL);
+
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_dspp.h b/drivers/gpu/drm/msm/sde/sde_hw_dspp.h
index 6020476..70b3e56 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_dspp.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_dspp.h
@@ -192,6 +192,7 @@
* should be called once before accessing every dspp.
* @idx: DSPP index for which driver object is required
* @addr: Mapped register io address of MDP
+ * @Return: pointer to structure or ERR_PTR
*/
struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx,
void __iomem *addr,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c
index 6a91a65..24f16c6 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c
@@ -31,9 +31,9 @@
#define MDP_INTF_4_OFF 0x6D000
#define MDP_AD4_0_OFF 0x7D000
#define MDP_AD4_1_OFF 0x7E000
-#define MDP_AD4_INTR_EN_OFF 0x41c
-#define MDP_AD4_INTR_CLEAR_OFF 0x424
-#define MDP_AD4_INTR_STATUS_OFF 0x420
+#define MDP_AD4_INTR_EN_OFF 0x41c
+#define MDP_AD4_INTR_CLEAR_OFF 0x424
+#define MDP_AD4_INTR_STATUS_OFF 0x420
/**
* WB interrupt status bit definitions
@@ -87,7 +87,7 @@
* Pingpong Secondary interrupt status bit definitions
*/
#define SDE_INTR_PING_PONG_S0_AUTOREFRESH_DONE BIT(0)
-#define SDE_INTR_PING_PONG_S0_WR_PTR BIT(4)
+#define SDE_INTR_PING_PONG_S0_WR_PTR BIT(4)
#define SDE_INTR_PING_PONG_S0_RD_PTR BIT(8)
#define SDE_INTR_PING_PONG_S0_TEAR_DETECTED BIT(22)
#define SDE_INTR_PING_PONG_S0_TE_DETECTED BIT(28)
@@ -711,6 +711,9 @@
static void sde_hw_intr_set_mask(struct sde_hw_intr *intr, uint32_t reg_off,
uint32_t mask)
{
+ if (!intr)
+ return;
+
SDE_REG_WRITE(&intr->hw, reg_off, mask);
}
@@ -725,6 +728,9 @@
u32 irq_status;
unsigned long irq_flags;
+ if (!intr)
+ return;
+
/*
* The dispatcher will save the IRQ status before calling here.
* Now need to go through each IRQ status and find matching
@@ -741,6 +747,10 @@
start_idx = reg_idx * 32;
end_idx = start_idx + 32;
+ if (start_idx >= ARRAY_SIZE(sde_irq_map) ||
+ end_idx > ARRAY_SIZE(sde_irq_map))
+ continue;
+
/*
* Search through matching intr status from irq map.
* start_idx and end_idx defined the search range in
@@ -784,6 +794,9 @@
const char *dbgstr = NULL;
uint32_t cache_irq_mask;
+ if (!intr)
+ return -EINVAL;
+
if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(sde_irq_map)) {
pr_err("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
@@ -825,6 +838,9 @@
const char *dbgstr = NULL;
uint32_t cache_irq_mask;
+ if (!intr)
+ return -EINVAL;
+
if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(sde_irq_map)) {
pr_err("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
@@ -861,6 +877,9 @@
{
int i;
+ if (!intr)
+ return -EINVAL;
+
for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++)
SDE_REG_WRITE(&intr->hw, sde_intr_set[i].clr_off, 0xffffffff);
@@ -871,6 +890,9 @@
{
int i;
+ if (!intr)
+ return -EINVAL;
+
for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++)
SDE_REG_WRITE(&intr->hw, sde_intr_set[i].en_off, 0x00000000);
@@ -880,15 +902,23 @@
static int sde_hw_intr_get_valid_interrupts(struct sde_hw_intr *intr,
uint32_t *mask)
{
+ if (!intr || !mask)
+ return -EINVAL;
+
*mask = IRQ_SOURCE_MDP | IRQ_SOURCE_DSI0 | IRQ_SOURCE_DSI1
| IRQ_SOURCE_HDMI | IRQ_SOURCE_EDP;
+
return 0;
}
static int sde_hw_intr_get_interrupt_sources(struct sde_hw_intr *intr,
uint32_t *sources)
{
+ if (!intr || !sources)
+ return -EINVAL;
+
*sources = SDE_REG_READ(&intr->hw, HW_INTR_STATUS);
+
return 0;
}
@@ -898,6 +928,9 @@
u32 enable_mask;
unsigned long irq_flags;
+ if (!intr)
+ return;
+
spin_lock_irqsave(&intr->status_lock, irq_flags);
for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++) {
/* Read interrupt status */
@@ -924,6 +957,9 @@
int reg_idx;
unsigned long irq_flags;
+ if (!intr)
+ return;
+
spin_lock_irqsave(&intr->mask_lock, irq_flags);
reg_idx = sde_irq_map[irq_idx].reg_idx;
@@ -940,6 +976,9 @@
unsigned long irq_flags;
u32 intr_status;
+ if (!intr)
+ return 0;
+
spin_lock_irqsave(&intr->mask_lock, irq_flags);
reg_idx = sde_irq_map[irq_idx].reg_idx;
@@ -974,7 +1013,7 @@
static struct sde_mdss_base_cfg *__intr_offset(struct sde_mdss_cfg *m,
void __iomem *addr, struct sde_hw_blk_reg_map *hw)
{
- if (m->mdp_count == 0)
+ if (!m || !addr || !hw || m->mdp_count == 0)
return NULL;
hw->base_off = addr;
@@ -986,9 +1025,13 @@
struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr,
struct sde_mdss_cfg *m)
{
- struct sde_hw_intr *intr = kzalloc(sizeof(*intr), GFP_KERNEL);
+ struct sde_hw_intr *intr;
struct sde_mdss_base_cfg *cfg;
+ if (!addr || !m)
+ return ERR_PTR(-EINVAL);
+
+ intr = kzalloc(sizeof(*intr), GFP_KERNEL);
if (!intr)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h
index 7991994..aaba1be 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h
@@ -25,7 +25,7 @@
#define IRQ_SOURCE_DSI1 BIT(5)
#define IRQ_SOURCE_HDMI BIT(8)
#define IRQ_SOURCE_EDP BIT(12)
-#define IRQ_SOURCE_MHL BIT(16)
+#define IRQ_SOURCE_MHL BIT(16)
/**
* sde_intr_type - HW Interrupt Type
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.c b/drivers/gpu/drm/msm/sde/sde_hw_top.c
index 3ba7a51..cf54611 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_top.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_top.c
@@ -39,13 +39,15 @@
static void sde_hw_setup_split_pipe(struct sde_hw_mdp *mdp,
struct split_pipe_cfg *cfg)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
u32 upper_pipe = 0;
u32 lower_pipe = 0;
if (!mdp || !cfg)
return;
+ c = &mdp->hw;
+
if (cfg->en) {
if (cfg->mode == INTF_MODE_CMD) {
lower_pipe = FLD_SPLIT_DISPLAY_CMD;
@@ -107,9 +109,14 @@
static void sde_hw_setup_cdm_output(struct sde_hw_mdp *mdp,
struct cdm_output_cfg *cfg)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
u32 out_ctl = 0;
+ if (!mdp || !cfg)
+ return;
+
+ c = &mdp->hw;
+
if (cfg->wb_en)
out_ctl |= BIT(24);
else if (cfg->intf_en)
@@ -121,11 +128,16 @@
static bool sde_hw_setup_clk_force_ctrl(struct sde_hw_mdp *mdp,
enum sde_clk_ctrl_type clk_ctrl, bool enable)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
u32 reg_off, bit_off;
u32 reg_val, new_val;
bool clk_forced_on;
+ if (!mdp)
+ return false;
+
+ c = &mdp->hw;
+
if (clk_ctrl <= SDE_CLK_CTRL_NONE || clk_ctrl >= SDE_CLK_CTRL_MAX)
return false;
@@ -150,9 +162,14 @@
static void sde_hw_get_danger_status(struct sde_hw_mdp *mdp,
struct sde_danger_safe_status *status)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
u32 value;
+ if (!mdp || !status)
+ return;
+
+ c = &mdp->hw;
+
value = SDE_REG_READ(c, DANGER_STATUS);
status->mdp = (value >> 0) & 0x3;
status->sspp[SSPP_VIG0] = (value >> 4) & 0x3;
@@ -178,9 +195,14 @@
static void sde_hw_get_safe_status(struct sde_hw_mdp *mdp,
struct sde_danger_safe_status *status)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
u32 value;
+ if (!mdp || !status)
+ return;
+
+ c = &mdp->hw;
+
value = SDE_REG_READ(c, SAFE_STATUS);
status->mdp = (value >> 0) & 0x1;
status->sspp[SSPP_VIG0] = (value >> 4) & 0x1;
@@ -205,7 +227,12 @@
static void sde_hw_setup_dce(struct sde_hw_mdp *mdp, u32 dce_sel)
{
- struct sde_hw_blk_reg_map *c = &mdp->hw;
+ struct sde_hw_blk_reg_map *c;
+
+ if (!mdp)
+ return;
+
+ c = &mdp->hw;
SDE_REG_WRITE(c, DCE_SEL, dce_sel);
}
@@ -246,6 +273,9 @@
{
int i;
+ if (!m || !addr || !b)
+ return ERR_PTR(-EINVAL);
+
for (i = 0; i < m->mdp_count; i++) {
if (mdp == m->mdp[i].id) {
b->base_off = addr;
diff --git a/drivers/gpu/drm/msm/sde/sde_wb.c b/drivers/gpu/drm/msm/sde/sde_wb.c
index 2220925..b2665be 100644
--- a/drivers/gpu/drm/msm/sde/sde_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_wb.c
@@ -286,6 +286,27 @@
return 0;
}
+int sde_wb_get_topology(const struct drm_display_mode *drm_mode,
+ struct msm_display_topology *topology, u32 max_mixer_width)
+{
+ const u32 dual_lm = 2;
+ const u32 single_lm = 1;
+ const u32 single_intf = 1;
+ const u32 no_enc = 0;
+
+ if (!drm_mode || !topology || !max_mixer_width) {
+ pr_err("invalid params\n");
+ return -EINVAL;
+ }
+
+ topology->num_lm = (max_mixer_width <= drm_mode->hdisplay) ?
+ dual_lm : single_lm;
+ topology->num_enc = no_enc;
+ topology->num_intf = single_intf;
+
+ return 0;
+}
+
int sde_wb_connector_post_init(struct drm_connector *connector,
void *info,
void *display)
diff --git a/drivers/gpu/drm/msm/sde/sde_wb.h b/drivers/gpu/drm/msm/sde/sde_wb.h
index 4e33595..205ff24 100644
--- a/drivers/gpu/drm/msm/sde/sde_wb.h
+++ b/drivers/gpu/drm/msm/sde/sde_wb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,7 @@
* @wb_lock Serialization lock for writeback context structure
* @connector: Connector associated with writeback device
* @encoder: Encoder associated with writeback device
+ * @max_mixer_width: Max width supported by SDE LM HW block
* @count_modes: Length of writeback connector modes array
* @modes: Writeback connector modes array
*/
@@ -49,6 +50,8 @@
struct drm_encoder *encoder;
enum drm_connector_status detect_status;
+ u32 max_mixer_width;
+
u32 count_modes;
struct drm_mode_modeinfo *modes;
};
@@ -183,6 +186,17 @@
int sde_wb_get_info(struct msm_display_info *info, void *display);
/**
+ * sde_wb_get_topology - retrieve current topology for the mode selected
+ * @drm_mode: Display mode set for the display
+ * @topology: Out parameter. Topology for the mode.
+ * @max_mixer_width: max width supported by HW layer mixer
+ * Returns: zero on success
+ */
+int sde_wb_get_topology(const struct drm_display_mode *drm_mode,
+ struct msm_display_topology *topology,
+ u32 max_mixer_width);
+
+/**
* sde_wb_connector_get_wb - retrieve writeback device of the given connector
* @connector: Pointer to drm connector
* Returns: Pointer to writeback device on success; NULL otherwise
diff --git a/drivers/gpu/drm/msm/sde_power_handle.h b/drivers/gpu/drm/msm/sde_power_handle.h
index b26ef9f..d753f0a 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.h
+++ b/drivers/gpu/drm/msm/sde_power_handle.h
@@ -16,9 +16,9 @@
#define MAX_CLIENT_NAME_LEN 128
-#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA 64000
+#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA 2000000000
#define SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA 0
-#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 64000
+#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 2000000000
#define SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA 0
#include <linux/sde_io_util.h>
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index d762904..1f770c3 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -28,16 +28,19 @@
#include <drm/drmP.h>
#include <drm/drm_irq.h>
#include "sde_rsc_priv.h"
+#include "sde_dbg.h"
-/* this time is ~0.02ms */
-#define RSC_BACKOFF_TIME_NS 20000
+/* worst case time to execute the one tcs vote(sleep/wake) - ~1ms */
+#define TCS_CASE_EXECUTION_TIME 1064000
-/* next two values should be same based on doc */
+/* this time is ~1ms - only wake tcs in any mode */
+#define RSC_BACKOFF_TIME_NS (TCS_CASE_EXECUTION_TIME + 100)
-/* this time is ~0.2ms */
-#define RSC_MODE_THRESHOLD_TIME_IN_NS 200000
-/* this time is ~0.2ms */
-#define RSC_TIME_SLOT_0_NS 200000
+/* this time is ~1ms - only wake TCS in mode-0 */
+#define RSC_MODE_THRESHOLD_TIME_IN_NS ((TCS_CASE_EXECUTION_TIME >> 1) + 100)
+
+/* this time is ~2ms - sleep+ wake TCS in mode-1 */
+#define RSC_TIME_SLOT_0_NS ((TCS_CASE_EXECUTION_TIME * 2) + 100)
#define DEFAULT_PANEL_FPS 60
#define DEFAULT_PANEL_JITTER 5
@@ -74,6 +77,7 @@
{
struct sde_rsc_client *client;
struct sde_rsc_priv *rsc;
+ static int id;
if (!client_name) {
pr_err("client name is null- not supported\n");
@@ -83,7 +87,7 @@
return ERR_PTR(-EINVAL);
} else if (!rsc_prv_list[rsc_index]) {
pr_err("rsc not probed yet or not available\n");
- return ERR_PTR(-EINVAL);
+ return NULL;
}
rsc = rsc_prv_list[rsc_index];
@@ -95,12 +99,14 @@
strlcpy(client->name, client_name, MAX_RSC_CLIENT_NAME_LEN);
client->current_state = SDE_RSC_IDLE_STATE;
client->rsc_index = rsc_index;
+ client->id = id;
if (is_primary_client)
rsc->primary_client = client;
pr_debug("client %s rsc index:%d primary:%d\n", client_name,
rsc_index, is_primary_client);
list_add(&client->list, &rsc->client_list);
+ id++;
mutex_unlock(&rsc->client_lock);
return client;
@@ -381,6 +387,8 @@
} else if (rsc->hw_ops.state_update) {
rc = rsc->hw_ops.state_update(rsc, SDE_RSC_IDLE_STATE);
+ if (!rc)
+ rpmh_mode_solver_set(rsc->disp_rsc, false);
}
return rc;
@@ -413,8 +421,11 @@
if (client->current_state == SDE_RSC_VID_STATE)
goto end;
- if (rsc->hw_ops.state_update)
+ if (rsc->hw_ops.state_update) {
rc = rsc->hw_ops.state_update(rsc, SDE_RSC_CMD_STATE);
+ if (!rc)
+ rpmh_mode_solver_set(rsc->disp_rsc, true);
+ }
/* wait for vsync for vid to cmd state switch */
if (!rc && (rsc->current_state == SDE_RSC_VID_STATE))
@@ -434,8 +445,11 @@
(client->current_state == SDE_RSC_CMD_STATE))
goto end;
- if (rsc->hw_ops.state_update)
+ if (rsc->hw_ops.state_update) {
rc = rsc->hw_ops.state_update(rsc, SDE_RSC_CLK_STATE);
+ if (!rc)
+ rpmh_mode_solver_set(rsc->disp_rsc, false);
+ }
/* wait for vsync for cmd to clk state switch */
if (!rc && rsc->primary_client &&
@@ -457,8 +471,11 @@
sde_rsc_timer_calculate(rsc, config);
/* video state switch should be done immediately */
- if (rsc->hw_ops.state_update)
+ if (rsc->hw_ops.state_update) {
rc = rsc->hw_ops.state_update(rsc, SDE_RSC_VID_STATE);
+ if (!rc)
+ rpmh_mode_solver_set(rsc->disp_rsc, false);
+ }
/* wait for vsync for cmd to vid state switch */
if (!rc && rsc->primary_client &&
@@ -502,6 +519,8 @@
return -EINVAL;
mutex_lock(&rsc->client_lock);
+ SDE_EVT32(caller_client->id, caller_client->current_state,
+ state, rsc->current_state, SDE_EVTLOG_FUNC_ENTRY);
caller_client->crtc_id = crtc_id;
caller_client->current_state = state;
@@ -559,14 +578,20 @@
if (rc == STATE_UPDATE_NOT_ALLOWED) {
rc = 0;
+ SDE_EVT32(caller_client->id, caller_client->current_state,
+ state, rsc->current_state, rc, SDE_EVTLOG_FUNC_CASE1);
goto clk_disable;
} else if (rc) {
pr_debug("state:%d update failed rc:%d\n", state, rc);
+ SDE_EVT32(caller_client->id, caller_client->current_state,
+ state, rsc->current_state, rc, SDE_EVTLOG_FUNC_CASE2);
goto clk_disable;
}
pr_debug("state switch successfully complete: %d\n", state);
rsc->current_state = state;
+ SDE_EVT32(caller_client->id, caller_client->current_state,
+ state, rsc->current_state, SDE_EVTLOG_FUNC_EXIT);
clk_disable:
if (rsc->current_state == SDE_RSC_IDLE_STATE)
@@ -1063,9 +1088,6 @@
pr_err("sde rsc:get display rsc failed ret:%d\n", ret);
goto sde_rsc_fail;
}
- rpmh_invalidate(rsc->disp_rsc);
- /* call flush to disable the disp rsc interrupt */
- rpmh_flush(rsc->disp_rsc);
ret = msm_dss_ioremap_byname(pdev, &rsc->wrapper_io, "wrapper");
if (ret) {
diff --git a/drivers/gpu/drm/msm/sde_rsc_hw.c b/drivers/gpu/drm/msm/sde_rsc_hw.c
index b63fbc6..c87dac4 100644
--- a/drivers/gpu/drm/msm/sde_rsc_hw.c
+++ b/drivers/gpu/drm/msm/sde_rsc_hw.c
@@ -95,6 +95,7 @@
#define SDE_RSCC_F1_QTMR_V1_CNTP_CTL 0x302C
#define MAX_CHECK_LOOPS 500
+#define POWER_CTRL_BIT_12 12
static void rsc_event_trigger(struct sde_rsc_priv *rsc, uint32_t event_type)
{
@@ -191,27 +192,27 @@
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x18,
0xa138ebaa, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x1c,
- 0xe0a581e1, rsc->debug_mode);
+ 0xaca581e1, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x20,
- 0x82e2a2ed, rsc->debug_mode);
+ 0xe2a2ede0, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x24,
- 0x88ea8a39, rsc->debug_mode);
+ 0xea8a3982, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x28,
- 0xa6e9a920, rsc->debug_mode);
+ 0xa920888c, rsc->debug_mode);
/* tcs sleep sequence */
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x2c,
- 0xa92089e6, rsc->debug_mode);
+ 0x89e6a6e9, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x30,
- 0x89e7a7e9, rsc->debug_mode);
+ 0xa7e9a920, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_MEM_0_DRV0 + 0x34,
- 0x00000020, rsc->debug_mode);
+ 0x002079e7, rsc->debug_mode);
/* branch address */
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_CFG_BR_ADDR_0_DRV0,
- 0x29, rsc->debug_mode);
+ 0x2b, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SEQ_CFG_BR_ADDR_1_DRV0,
- 0x2f, rsc->debug_mode);
+ 0x31, rsc->debug_mode);
return 0;
}
@@ -266,7 +267,7 @@
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM0_DRV0_MODE0,
mode_0_start_addr, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM1_DRV0_MODE0,
- 0x80000010, rsc->debug_mode);
+ 0x80000000, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM2_DRV0_MODE0,
rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM3_DRV0_MODE0,
@@ -275,7 +276,7 @@
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM0_DRV0_MODE1,
mode_1_start_addr, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM1_DRV0_MODE1,
- 0x80000010, rsc->debug_mode);
+ 0x80000000, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM2_DRV0_MODE1,
rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM3_DRV0_MODE1,
@@ -284,9 +285,9 @@
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM0_DRV0_MODE2,
mode_2_start_addr, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM1_DRV0_MODE2,
- 0x80000010, rsc->debug_mode);
+ 0x80000000, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM2_DRV0_MODE2,
- rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode);
+ 0x0, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_MODE_PARM3_DRV0_MODE2,
rsc->timer_config.pdc_backoff_time_ns, rsc->debug_mode);
@@ -297,6 +298,7 @@
{
int rc;
int count, wrapper_status;
+ unsigned long reg;
if (rsc->power_collapse_block)
return -EINVAL;
@@ -355,6 +357,18 @@
if (rc) {
pr_err("vdd fs is still enabled\n");
goto end;
+ } else {
+ rc = -EINVAL;
+ /* this wait is required to turn off the rscc clocks */
+ for (count = MAX_CHECK_LOOPS; count > 0; count--) {
+ reg = dss_reg_r(&rsc->wrapper_io,
+ SDE_RSCC_PWR_CTRL, rsc->debug_mode);
+ if (test_bit(POWER_CTRL_BIT_12, ®)) {
+ rc = 0;
+ break;
+ }
+ usleep_range(1, 2);
+ }
}
if ((rsc->current_state == SDE_RSC_VID_STATE) ||
@@ -458,9 +472,6 @@
0x1, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SOLVER_OVERRIDE_CTRL_DRV0,
0x0, rsc->debug_mode);
- dss_reg_w(&rsc->drv_io,
- SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x7,
- rsc->debug_mode);
reg = dss_reg_r(&rsc->wrapper_io,
SDE_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode);
reg |= (BIT(0) | BIT(8));
@@ -484,9 +495,6 @@
reg &= ~(BIT(1) | BIT(0));
dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
reg, rsc->debug_mode);
- dss_reg_w(&rsc->drv_io,
- SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x5,
- rsc->debug_mode);
/* make sure that solver mode is override */
wmb();
@@ -501,9 +509,6 @@
reg &= ~(BIT(8) | BIT(0));
dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
reg, rsc->debug_mode);
- dss_reg_w(&rsc->drv_io,
- SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x5,
- rsc->debug_mode);
/* make sure that solver mode is disabled */
wmb();
break;
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index 69b639a..14a19a4 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.h
@@ -111,14 +111,6 @@
#define A6XX_VSC_ADDR_MODE_CNTL 0xC01
/* RBBM registers */
-#define A6XX_RBBM_VBIF_CLIENT_QOS_CNTL 0x10
-#define A6XX_RBBM_INTERFACE_HANG_INT_CNTL 0x1f
-#define A6XX_RBBM_INT_CLEAR_CMD 0x37
-#define A6XX_RBBM_INT_0_MASK 0x38
-#define A6XX_RBBM_SW_RESET_CMD 0x43
-#define A6XX_RBBM_BLOCK_SW_RESET_CMD 0x45
-#define A6XX_RBBM_BLOCK_SW_RESET_CMD2 0x46
-#define A6XX_RBBM_CLOCK_CNTL 0xAE
#define A6XX_RBBM_INT_0_STATUS 0x201
#define A6XX_RBBM_STATUS 0x210
#define A6XX_RBBM_STATUS3 0x213
@@ -390,6 +382,8 @@
#define A6XX_RBBM_PERFCTR_RBBM_SEL_2 0x509
#define A6XX_RBBM_PERFCTR_RBBM_SEL_3 0x50A
+#define A6XX_RBBM_ISDB_CNT 0x533
+
#define A6XX_RBBM_SECVID_TRUST_CNTL 0xF400
#define A6XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO 0xF800
#define A6XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI 0xF801
@@ -397,6 +391,122 @@
#define A6XX_RBBM_SECVID_TSB_CNTL 0xF803
#define A6XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL 0xF810
+#define A6XX_RBBM_VBIF_CLIENT_QOS_CNTL 0x00010
+#define A6XX_RBBM_INTERFACE_HANG_INT_CNTL 0x0001f
+#define A6XX_RBBM_INT_CLEAR_CMD 0x00037
+#define A6XX_RBBM_INT_0_MASK 0x00038
+#define A6XX_RBBM_SP_HYST_CNT 0x00042
+#define A6XX_RBBM_SW_RESET_CMD 0x00043
+#define A6XX_RBBM_RAC_THRESHOLD_CNT 0x00044
+#define A6XX_RBBM_BLOCK_SW_RESET_CMD 0x00045
+#define A6XX_RBBM_BLOCK_SW_RESET_CMD2 0x00046
+#define A6XX_RBBM_CLOCK_CNTL 0x000ae
+#define A6XX_RBBM_CLOCK_CNTL_SP0 0x000b0
+#define A6XX_RBBM_CLOCK_CNTL_SP1 0x000b1
+#define A6XX_RBBM_CLOCK_CNTL_SP2 0x000b2
+#define A6XX_RBBM_CLOCK_CNTL_SP3 0x000b3
+#define A6XX_RBBM_CLOCK_CNTL2_SP0 0x000b4
+#define A6XX_RBBM_CLOCK_CNTL2_SP1 0x000b5
+#define A6XX_RBBM_CLOCK_CNTL2_SP2 0x000b6
+#define A6XX_RBBM_CLOCK_CNTL2_SP3 0x000b7
+#define A6XX_RBBM_CLOCK_DELAY_SP0 0x000b8
+#define A6XX_RBBM_CLOCK_DELAY_SP1 0x000b9
+#define A6XX_RBBM_CLOCK_DELAY_SP2 0x000ba
+#define A6XX_RBBM_CLOCK_DELAY_SP3 0x000bb
+#define A6XX_RBBM_CLOCK_HYST_SP0 0x000bc
+#define A6XX_RBBM_CLOCK_HYST_SP1 0x000bd
+#define A6XX_RBBM_CLOCK_HYST_SP2 0x000be
+#define A6XX_RBBM_CLOCK_HYST_SP3 0x000bf
+#define A6XX_RBBM_CLOCK_CNTL_TP0 0x000c0
+#define A6XX_RBBM_CLOCK_CNTL_TP1 0x000c1
+#define A6XX_RBBM_CLOCK_CNTL_TP2 0x000c2
+#define A6XX_RBBM_CLOCK_CNTL_TP3 0x000c3
+#define A6XX_RBBM_CLOCK_CNTL2_TP0 0x000c4
+#define A6XX_RBBM_CLOCK_CNTL2_TP1 0x000c5
+#define A6XX_RBBM_CLOCK_CNTL2_TP2 0x000c6
+#define A6XX_RBBM_CLOCK_CNTL2_TP3 0x000c7
+#define A6XX_RBBM_CLOCK_CNTL3_TP0 0x000c8
+#define A6XX_RBBM_CLOCK_CNTL3_TP1 0x000c9
+#define A6XX_RBBM_CLOCK_CNTL3_TP2 0x000ca
+#define A6XX_RBBM_CLOCK_CNTL3_TP3 0x000cb
+#define A6XX_RBBM_CLOCK_CNTL4_TP0 0x000cc
+#define A6XX_RBBM_CLOCK_CNTL4_TP1 0x000cd
+#define A6XX_RBBM_CLOCK_CNTL4_TP2 0x000ce
+#define A6XX_RBBM_CLOCK_CNTL4_TP3 0x000cf
+#define A6XX_RBBM_CLOCK_DELAY_TP0 0x000d0
+#define A6XX_RBBM_CLOCK_DELAY_TP1 0x000d1
+#define A6XX_RBBM_CLOCK_DELAY_TP2 0x000d2
+#define A6XX_RBBM_CLOCK_DELAY_TP3 0x000d3
+#define A6XX_RBBM_CLOCK_DELAY2_TP0 0x000d4
+#define A6XX_RBBM_CLOCK_DELAY2_TP1 0x000d5
+#define A6XX_RBBM_CLOCK_DELAY2_TP2 0x000d6
+#define A6XX_RBBM_CLOCK_DELAY2_TP3 0x000d7
+#define A6XX_RBBM_CLOCK_DELAY3_TP0 0x000d8
+#define A6XX_RBBM_CLOCK_DELAY3_TP1 0x000d9
+#define A6XX_RBBM_CLOCK_DELAY3_TP2 0x000da
+#define A6XX_RBBM_CLOCK_DELAY3_TP3 0x000db
+#define A6XX_RBBM_CLOCK_DELAY4_TP0 0x000dc
+#define A6XX_RBBM_CLOCK_DELAY4_TP1 0x000dd
+#define A6XX_RBBM_CLOCK_DELAY4_TP2 0x000de
+#define A6XX_RBBM_CLOCK_DELAY4_TP3 0x000df
+#define A6XX_RBBM_CLOCK_HYST_TP0 0x000e0
+#define A6XX_RBBM_CLOCK_HYST_TP1 0x000e1
+#define A6XX_RBBM_CLOCK_HYST_TP2 0x000e2
+#define A6XX_RBBM_CLOCK_HYST_TP3 0x000e3
+#define A6XX_RBBM_CLOCK_HYST2_TP0 0x000e4
+#define A6XX_RBBM_CLOCK_HYST2_TP1 0x000e5
+#define A6XX_RBBM_CLOCK_HYST2_TP2 0x000e6
+#define A6XX_RBBM_CLOCK_HYST2_TP3 0x000e7
+#define A6XX_RBBM_CLOCK_HYST3_TP0 0x000e8
+#define A6XX_RBBM_CLOCK_HYST3_TP1 0x000e9
+#define A6XX_RBBM_CLOCK_HYST3_TP2 0x000ea
+#define A6XX_RBBM_CLOCK_HYST3_TP3 0x000eb
+#define A6XX_RBBM_CLOCK_HYST4_TP0 0x000ec
+#define A6XX_RBBM_CLOCK_HYST4_TP1 0x000ed
+#define A6XX_RBBM_CLOCK_HYST4_TP2 0x000ee
+#define A6XX_RBBM_CLOCK_HYST4_TP3 0x000ef
+#define A6XX_RBBM_CLOCK_CNTL_RB0 0x000f0
+#define A6XX_RBBM_CLOCK_CNTL_RB1 0x000f1
+#define A6XX_RBBM_CLOCK_CNTL_RB2 0x000f2
+#define A6XX_RBBM_CLOCK_CNTL_RB3 0x000f3
+#define A6XX_RBBM_CLOCK_CNTL2_RB0 0x000f4
+#define A6XX_RBBM_CLOCK_CNTL2_RB1 0x000f5
+#define A6XX_RBBM_CLOCK_CNTL2_RB2 0x000f6
+#define A6XX_RBBM_CLOCK_CNTL2_RB3 0x000f7
+#define A6XX_RBBM_CLOCK_CNTL_CCU0 0x000f8
+#define A6XX_RBBM_CLOCK_CNTL_CCU1 0x000f9
+#define A6XX_RBBM_CLOCK_CNTL_CCU2 0x000fa
+#define A6XX_RBBM_CLOCK_CNTL_CCU3 0x000fb
+#define A6XX_RBBM_CLOCK_HYST_RB_CCU0 0x00100
+#define A6XX_RBBM_CLOCK_HYST_RB_CCU1 0x00101
+#define A6XX_RBBM_CLOCK_HYST_RB_CCU2 0x00102
+#define A6XX_RBBM_CLOCK_HYST_RB_CCU3 0x00103
+#define A6XX_RBBM_CLOCK_CNTL_RAC 0x00104
+#define A6XX_RBBM_CLOCK_CNTL2_RAC 0x00105
+#define A6XX_RBBM_CLOCK_DELAY_RAC 0x00106
+#define A6XX_RBBM_CLOCK_HYST_RAC 0x00107
+#define A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM 0x00108
+#define A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM 0x00109
+#define A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM 0x0010a
+#define A6XX_RBBM_CLOCK_CNTL_UCHE 0x0010b
+#define A6XX_RBBM_CLOCK_CNTL2_UCHE 0x0010c
+#define A6XX_RBBM_CLOCK_CNTL3_UCHE 0x0010d
+#define A6XX_RBBM_CLOCK_CNTL4_UCHE 0x0010e
+#define A6XX_RBBM_CLOCK_DELAY_UCHE 0x0010f
+#define A6XX_RBBM_CLOCK_HYST_UCHE 0x00110
+#define A6XX_RBBM_CLOCK_MODE_VFD 0x00111
+#define A6XX_RBBM_CLOCK_DELAY_VFD 0x00112
+#define A6XX_RBBM_CLOCK_HYST_VFD 0x00113
+#define A6XX_RBBM_CLOCK_MODE_GPC 0x00114
+#define A6XX_RBBM_CLOCK_DELAY_GPC 0x00115
+#define A6XX_RBBM_CLOCK_HYST_GPC 0x00116
+#define A6XX_RBBM_CLOCK_DELAY_HLSQ_2 0x00117
+#define A6XX_RBBM_CLOCK_CNTL_GMU_GX 0x00118
+#define A6XX_RBBM_CLOCK_DELAY_GMU_GX 0x00119
+#define A6XX_RBBM_CLOCK_HYST_GMU_GX 0x0011a
+#define A6XX_RBBM_CLOCK_MODE_HLSQ 0x0011b
+#define A6XX_RBBM_CLOCK_DELAY_HLSQ 0x0011c
+
/* DBGC_CFG registers */
#define A6XX_DBGC_CFG_DBGBUS_SEL_A 0x600
#define A6XX_DBGC_CFG_DBGBUS_SEL_B 0x601
@@ -666,6 +776,7 @@
#define A6XX_CX_DBGC_CFG_DBGBUS_SEL_PING_BLK_SEL_SHIFT 0x8
/* GMU control registers */
+#define A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL 0x1A880
#define A6XX_GMU_GX_SPTPRAC_POWER_CONTROL 0x1A881
#define A6XX_GMU_CM3_ITCM_START 0x1B400
#define A6XX_GMU_CM3_DTCM_START 0x1C400
@@ -722,6 +833,9 @@
#define A6XX_GMU_AO_HOST_INTERRUPT_CLR 0x23B04
#define A6XX_GMU_AO_HOST_INTERRUPT_STATUS 0x23B05
#define A6XX_GMU_AO_HOST_INTERRUPT_MASK 0x23B06
+#define A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL 0x23B09
+#define A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL 0x23B0A
+#define A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL 0x23B0B
#define A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS 0x23B0C
#define A6XX_GMU_AHB_FENCE_STATUS 0x23B13
#define A6XX_GMU_RBBM_INT_UNMASKED_STATUS 0x23B15
diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h
index 876ff0c..9a44f34 100644
--- a/drivers/gpu/msm/adreno-gpulist.h
+++ b/drivers/gpu/msm/adreno-gpulist.h
@@ -326,8 +326,7 @@
.major = 3,
.minor = 0,
.patchid = ANY_ID,
- .features = ADRENO_64BIT |
- ADRENO_GPMU | ADRENO_RPMH,
+ .features = ADRENO_64BIT | ADRENO_RPMH,
.sqefw_name = "a630_sqe.fw",
.zap_name = "a630_zap",
.gpudev = &adreno_a6xx_gpudev,
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 3c3f99f..b5546ef 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -59,6 +59,127 @@
{ adreno_is_a630, a630_vbif },
};
+
+struct kgsl_hwcg_reg {
+ unsigned int off;
+ unsigned int val;
+};
+static const struct kgsl_hwcg_reg a630_hwcg_regs[] = {
+ {A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL_SP1, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL_SP2, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL_SP3, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+ {A6XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220},
+ {A6XX_RBBM_CLOCK_CNTL2_SP2, 0x02222220},
+ {A6XX_RBBM_CLOCK_CNTL2_SP3, 0x02222220},
+ {A6XX_RBBM_CLOCK_DELAY_SP0, 0x0000F3CF},
+ {A6XX_RBBM_CLOCK_DELAY_SP1, 0x0000F3CF},
+ {A6XX_RBBM_CLOCK_DELAY_SP2, 0x0000F3CF},
+ {A6XX_RBBM_CLOCK_DELAY_SP3, 0x0000F3CF},
+ {A6XX_RBBM_CLOCK_HYST_SP0, 0x00000080},
+ {A6XX_RBBM_CLOCK_HYST_SP1, 0x00000080},
+ {A6XX_RBBM_CLOCK_HYST_SP2, 0x00000080},
+ {A6XX_RBBM_CLOCK_HYST_SP3, 0x00000080},
+ {A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL_TP1, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL_TP2, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL_TP3, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL3_TP1, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL3_TP2, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL3_TP3, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
+ {A6XX_RBBM_CLOCK_CNTL4_TP1, 0x00022222},
+ {A6XX_RBBM_CLOCK_CNTL4_TP2, 0x00022222},
+ {A6XX_RBBM_CLOCK_CNTL4_TP3, 0x00022222},
+ {A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+ {A6XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
+ {A6XX_RBBM_CLOCK_HYST_TP2, 0x77777777},
+ {A6XX_RBBM_CLOCK_HYST_TP3, 0x77777777},
+ {A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+ {A6XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
+ {A6XX_RBBM_CLOCK_HYST2_TP2, 0x77777777},
+ {A6XX_RBBM_CLOCK_HYST2_TP3, 0x77777777},
+ {A6XX_RBBM_CLOCK_HYST3_TP0, 0x07777777},
+ {A6XX_RBBM_CLOCK_HYST3_TP1, 0x07777777},
+ {A6XX_RBBM_CLOCK_HYST3_TP2, 0x07777777},
+ {A6XX_RBBM_CLOCK_HYST3_TP3, 0x07777777},
+ {A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
+ {A6XX_RBBM_CLOCK_HYST4_TP1, 0x00077777},
+ {A6XX_RBBM_CLOCK_HYST4_TP2, 0x00077777},
+ {A6XX_RBBM_CLOCK_HYST4_TP3, 0x00077777},
+ {A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY_TP2, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY_TP3, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY3_TP1, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY3_TP2, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY3_TP3, 0x11111111},
+ {A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
+ {A6XX_RBBM_CLOCK_DELAY4_TP1, 0x00011111},
+ {A6XX_RBBM_CLOCK_DELAY4_TP2, 0x00011111},
+ {A6XX_RBBM_CLOCK_DELAY4_TP3, 0x00011111},
+ {A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
+ {A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
+ {A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+ {A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL_RB1, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL_RB2, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL_RB3, 0x22222222},
+ {A6XX_RBBM_CLOCK_CNTL2_RB0, 0x00002222},
+ {A6XX_RBBM_CLOCK_CNTL2_RB1, 0x00002222},
+ {A6XX_RBBM_CLOCK_CNTL2_RB2, 0x00002222},
+ {A6XX_RBBM_CLOCK_CNTL2_RB3, 0x00002222},
+ {A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
+ {A6XX_RBBM_CLOCK_CNTL_CCU1, 0x00002220},
+ {A6XX_RBBM_CLOCK_CNTL_CCU2, 0x00002220},
+ {A6XX_RBBM_CLOCK_CNTL_CCU3, 0x00002220},
+ {A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
+ {A6XX_RBBM_CLOCK_HYST_RB_CCU1, 0x00040F00},
+ {A6XX_RBBM_CLOCK_HYST_RB_CCU2, 0x00040F00},
+ {A6XX_RBBM_CLOCK_HYST_RB_CCU3, 0x00040F00},
+ {A6XX_RBBM_CLOCK_CNTL_RAC, 0x05022022},
+ {A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+ {A6XX_RBBM_CLOCK_DELAY_RAC, 0x00010011},
+ {A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
+ {A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+ {A6XX_RBBM_CLOCK_MODE_GPC, 0x02222222},
+ {A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+ {A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+ {A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+ {A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+ {A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+ {A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+ {A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+ {A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
+ {A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
+ {A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
+ {A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
+ {A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
+ {A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555}
+};
+
+static const struct {
+ int (*devfunc)(struct adreno_device *adreno_dev);
+ const struct kgsl_hwcg_reg *regs;
+ unsigned int count;
+} a6xx_hwcg_registers[] = {
+ {adreno_is_a630, a630_hwcg_regs, ARRAY_SIZE(a630_hwcg_regs)}
+};
+
static struct a6xx_protected_regs {
unsigned int base;
unsigned int count;
@@ -125,7 +246,7 @@
unsigned int mmu_base = 0, mmu_range = 0, cur_range;
/* enable access protection to privileged registers */
- kgsl_regwrite(device, A6XX_CP_PROTECT_CNTL, 0x00000007);
+ kgsl_regwrite(device, A6XX_CP_PROTECT_CNTL, 0x00000003);
if (mmu_prot) {
mmu_base = mmu_prot->base;
@@ -181,6 +302,48 @@
kgsl_regwrite(device, A6XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL, 0x1);
}
+
+static void a6xx_hwcg_set(struct adreno_device *adreno_dev, bool on)
+{
+ struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
+ const struct kgsl_hwcg_reg *regs;
+ int i, j;
+
+ if (!test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(a6xx_hwcg_registers); i++) {
+ if (a6xx_hwcg_registers[i].devfunc(adreno_dev))
+ break;
+ }
+
+ if (i == ARRAY_SIZE(a6xx_hwcg_registers))
+ return;
+
+ regs = a6xx_hwcg_registers[i].regs;
+
+ /* Disable SP clock before programming HWCG registers */
+ kgsl_gmu_regrmw(device, A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 0, 0);
+
+ for (j = 0; j < a6xx_hwcg_registers[i].count; j++)
+ kgsl_regwrite(device, regs[j].off, on ? regs[j].val : 0);
+
+ if (kgsl_gmu_isenabled(device)) {
+ kgsl_gmu_regwrite(device, A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL,
+ 0x00020222);
+ kgsl_gmu_regwrite(device, A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL,
+ 0x00010111);
+ kgsl_gmu_regwrite(device, A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL,
+ 0x00050555);
+ }
+ /* Enable SP clock */
+ kgsl_gmu_regrmw(device, A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 0, 1);
+
+ /* enable top level HWCG */
+ kgsl_regwrite(device, A6XX_RBBM_CLOCK_CNTL, on ? 0x8AA8AA02 : 0);
+ kgsl_regwrite(device, A5XX_RBBM_ISDB_CNT, on ? 0x00000182 : 0x00000180);
+}
+
/*
* a6xx_start() - Device start
* @adreno_dev: Pointer to adreno device
@@ -197,6 +360,8 @@
if (!kgsl_gmu_isenabled(device))
/* Legacy idle management if gmu is disabled */
ADRENO_GPU_DEVICE(adreno_dev)->hw_isidle = NULL;
+ /* enable hardware clockgating */
+ a6xx_hwcg_set(adreno_dev, true);
adreno_vbif_start(adreno_dev, a6xx_vbif_platforms,
ARRAY_SIZE(a6xx_vbif_platforms));
@@ -235,6 +400,9 @@
/* Set the AHB default slave response to "ERROR" */
kgsl_regwrite(device, A6XX_CP_AHB_CNTL, 0x1);
+ /* Turn on performance counters */
+ kgsl_regwrite(device, A6XX_RBBM_PERFCTR_CNTL, 0x1);
+
if (of_property_read_u32(device->pdev->dev.of_node,
"qcom,highest-bank-bit", &bit))
bit = MIN_HBB;
@@ -282,8 +450,9 @@
kgsl_regwrite(device, A6XX_UCHE_MODE_CNTL, (glbl_inv << 29) |
(mal << 23) | (bit << 21));
+ /* Set hang detection threshold to 4 million cycles (0x3FFFF*16) */
kgsl_regwrite(device, A6XX_RBBM_INTERFACE_HANG_INT_CNTL,
- (1 << 30) | 0x4000);
+ (1 << 30) | 0x3ffff);
kgsl_regwrite(device, A6XX_UCHE_CLIENT_PF, 1);
@@ -1553,7 +1722,10 @@
else if (client_id != 3)
return fault_block[client_id];
+ mutex_lock(&device->mutex);
kgsl_regread(device, A6XX_UCHE_CLIENT_PF, &uche_client_id);
+ mutex_unlock(&device->mutex);
+
return uche_client[uche_client_id & A6XX_UCHE_CLIENT_PF_CLIENT_ID_MASK];
}
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index ba83cd7..01ecb01 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -121,6 +121,8 @@
unsigned int statetype;
const unsigned int *regs;
unsigned int num_sets;
+ unsigned int offset0;
+ unsigned int offset1;
} a6xx_dbgahb_ctx_clusters[] = {
{ CP_CLUSTER_SP_VS, 0x0002E000, 0x41, a6xx_sp_vs_hlsq_cluster,
ARRAY_SIZE(a6xx_sp_vs_hlsq_cluster) / 2 },
@@ -624,8 +626,8 @@
return val;
}
-static size_t a6xx_snapshot_cluster_dbgahb(struct kgsl_device *device, u8 *buf,
- size_t remain, void *priv)
+static size_t a6xx_legacy_snapshot_cluster_dbgahb(struct kgsl_device *device,
+ u8 *buf, size_t remain, void *priv)
{
struct kgsl_snapshot_mvc_regs *header =
(struct kgsl_snapshot_mvc_regs *)buf;
@@ -678,6 +680,63 @@
return data_size + sizeof(*header);
}
+static size_t a6xx_snapshot_cluster_dbgahb(struct kgsl_device *device, u8 *buf,
+ size_t remain, void *priv)
+{
+ struct kgsl_snapshot_mvc_regs *header =
+ (struct kgsl_snapshot_mvc_regs *)buf;
+ struct a6xx_cluster_dbgahb_regs_info *info =
+ (struct a6xx_cluster_dbgahb_regs_info *)priv;
+ struct a6xx_cluster_dbgahb_registers *cluster = info->cluster;
+ unsigned int data_size = 0;
+ unsigned int *data = (unsigned int *)(buf + sizeof(*header));
+ int i, j;
+ unsigned int *src;
+
+
+ if (crash_dump_valid == false)
+ return a6xx_legacy_snapshot_cluster_dbgahb(device, buf, remain,
+ info);
+
+ if (remain < sizeof(*header)) {
+ SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
+ return 0;
+ }
+
+ remain -= sizeof(*header);
+
+ header->ctxt_id = info->ctxt_id;
+ header->cluster_id = cluster->id;
+
+ src = (unsigned int *)(a6xx_crashdump_registers.hostptr +
+ (header->ctxt_id ? cluster->offset1 : cluster->offset0));
+
+ for (i = 0; i < cluster->num_sets; i++) {
+ unsigned int start;
+ unsigned int end;
+
+ start = cluster->regs[2 * i];
+ end = cluster->regs[2 * i + 1];
+
+ if (remain < (end - start + 3) * 4) {
+ SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
+ goto out;
+ }
+
+ remain -= (end - start + 3) * 4;
+ data_size += (end - start + 3) * 4;
+
+ *data++ = start | (1 << 31);
+ *data++ = end;
+ for (j = start; j <= end; j++)
+ *data++ = *src++;
+ }
+out:
+ return data_size + sizeof(*header);
+}
+
+
+
static size_t a6xx_snapshot_non_ctx_dbgahb(struct kgsl_device *device, u8 *buf,
size_t remain, void *priv)
{
@@ -1391,6 +1450,47 @@
return qwords;
}
+static int _a6xx_crashdump_init_ctx_dbgahb(uint64_t *ptr, uint64_t *offset)
+{
+ int qwords = 0;
+ unsigned int i, j, k;
+ unsigned int count;
+
+ for (i = 0; i < ARRAY_SIZE(a6xx_dbgahb_ctx_clusters); i++) {
+ struct a6xx_cluster_dbgahb_registers *cluster =
+ &a6xx_dbgahb_ctx_clusters[i];
+
+ cluster->offset0 = *offset;
+
+ for (j = 0; j < A6XX_NUM_CTXTS; j++) {
+ if (j == 1)
+ cluster->offset1 = *offset;
+
+ /* Program the aperture */
+ ptr[qwords++] =
+ ((cluster->statetype + j * 2) & 0xff) << 8;
+ ptr[qwords++] =
+ (((uint64_t)A6XX_HLSQ_DBG_READ_SEL << 44)) |
+ (1 << 21) | 1;
+
+ for (k = 0; k < cluster->num_sets; k++) {
+ unsigned int start = cluster->regs[2 * k];
+
+ count = REG_PAIR_COUNT(cluster->regs, k);
+ ptr[qwords++] =
+ a6xx_crashdump_registers.gpuaddr + *offset;
+ ptr[qwords++] =
+ (((uint64_t)(A6XX_HLSQ_DBG_AHB_READ_APERTURE +
+ start - cluster->regbase / 4) << 44)) |
+ count;
+
+ *offset += count * sizeof(unsigned int);
+ }
+ }
+ }
+ return qwords;
+}
+
void a6xx_crashdump_init(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
@@ -1458,6 +1558,26 @@
}
}
+ /* Calculate the script and data size for debug AHB registers */
+ for (i = 0; i < ARRAY_SIZE(a6xx_dbgahb_ctx_clusters); i++) {
+ struct a6xx_cluster_dbgahb_registers *cluster =
+ &a6xx_dbgahb_ctx_clusters[i];
+
+ for (j = 0; j < A6XX_NUM_CTXTS; j++) {
+
+ /* 16 bytes for programming the aperture */
+ script_size += 16;
+
+ /* Reading each pair of registers takes 16 bytes */
+ script_size += 16 * cluster->num_sets;
+
+ /* A dword per register read from the cluster list */
+ for (k = 0; k < cluster->num_sets; k++)
+ data_size += REG_PAIR_COUNT(cluster->regs, k) *
+ sizeof(unsigned int);
+ }
+ }
+
/* Now allocate the script and data buffers */
/* The script buffers needs 2 extra qwords on the end */
@@ -1497,6 +1617,8 @@
/* Program the capturescript for the MVC regsiters */
ptr += _a6xx_crashdump_init_mvc(ptr, &offset);
+ ptr += _a6xx_crashdump_init_ctx_dbgahb(ptr, &offset);
+
*ptr++ = 0;
*ptr++ = 0;
}
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index ab574d8..f217822 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -342,7 +342,7 @@
struct kgsl_device *device = dev_priv->device;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int ret;
- unsigned long local;
+ unsigned int local;
local = *flags & (KGSL_CONTEXT_PREAMBLE |
KGSL_CONTEXT_NO_GMEM_ALLOC |
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 32175f5..fbff535 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -54,10 +54,21 @@
/* Read always on registers */
if (!adreno_is_a3xx(adreno_dev)) {
- adreno_readreg64(adreno_dev,
- ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO,
- ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI,
- &time->ticks);
+ if (kgsl_gmu_isenabled(KGSL_DEVICE(adreno_dev))) {
+ uint32_t val_lo, val_hi;
+
+ adreno_read_gmureg(adreno_dev,
+ ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO, &val_lo);
+ adreno_read_gmureg(adreno_dev,
+ ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI, &val_hi);
+
+ time->ticks = (val_lo | ((uint64_t)val_hi << 32));
+ } else {
+ adreno_readreg64(adreno_dev,
+ ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO,
+ ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI,
+ &time->ticks);
+ }
/* Mask hi bits as they may be incorrect on some targets */
if (ADRENO_GPUREV(adreno_dev) >= 400 &&
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 15f68bf..8f49bc7 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1627,7 +1627,8 @@
/* If no profiling buffer was specified, clear the flag */
if (cmdobj->profiling_buf_entry == NULL)
- DRAWOBJ(cmdobj)->flags &= ~KGSL_DRAWOBJ_PROFILING;
+ DRAWOBJ(cmdobj)->flags &=
+ ~(unsigned long)KGSL_DRAWOBJ_PROFILING;
}
result = device->ftbl->queue_cmds(dev_priv, context, drawobj,
@@ -1716,7 +1717,8 @@
/* If no profiling buffer was specified, clear the flag */
if (cmdobj->profiling_buf_entry == NULL)
- DRAWOBJ(cmdobj)->flags &= ~KGSL_DRAWOBJ_PROFILING;
+ DRAWOBJ(cmdobj)->flags &=
+ ~(unsigned long)KGSL_DRAWOBJ_PROFILING;
}
result = device->ftbl->queue_cmds(dev_priv, context, drawobj,
@@ -2041,7 +2043,7 @@
unsigned long flags_requested = (VM_READ | VM_WRITE);
if (flags & KGSL_MEMFLAGS_GPUREADONLY)
- flags_requested &= ~VM_WRITE;
+ flags_requested &= ~(unsigned long)VM_WRITE;
if ((vma->vm_flags & flags_requested) == flags_requested)
return 0;
@@ -2135,7 +2137,7 @@
entry->memdesc.pagetable = pagetable;
entry->memdesc.size = (uint64_t) size;
entry->memdesc.useraddr = hostptr;
- entry->memdesc.flags |= KGSL_MEMFLAGS_USERMEM_ADDR;
+ entry->memdesc.flags |= (uint64_t)KGSL_MEMFLAGS_USERMEM_ADDR;
if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
int ret;
@@ -2166,7 +2168,7 @@
static void _setup_cache_mode(struct kgsl_mem_entry *entry,
struct vm_area_struct *vma)
{
- unsigned int mode;
+ uint64_t mode;
pgprot_t pgprot = vma->vm_page_prot;
if (pgprot_val(pgprot) == pgprot_val(pgprot_noncached(pgprot)))
@@ -2525,7 +2527,7 @@
entry->memdesc.size = 0;
/* USE_CPU_MAP is not impemented for ION. */
entry->memdesc.flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP);
- entry->memdesc.flags |= KGSL_MEMFLAGS_USERMEM_ION;
+ entry->memdesc.flags |= (uint64_t)KGSL_MEMFLAGS_USERMEM_ION;
sg_table = dma_buf_map_attachment(attach, DMA_TO_DEVICE);
@@ -3028,8 +3030,9 @@
if ((flags & KGSL_CACHEMODE_MASK) >> KGSL_CACHEMODE_SHIFT ==
KGSL_CACHEMODE_WRITETHROUGH) {
flags &= ~((uint64_t) KGSL_CACHEMODE_MASK);
- flags |= (KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT) &
- KGSL_CACHEMODE_MASK;
+ flags |= (uint64_t)((KGSL_CACHEMODE_WRITEBACK <<
+ KGSL_CACHEMODE_SHIFT) &
+ KGSL_CACHEMODE_MASK);
}
return flags;
}
@@ -3083,8 +3086,9 @@
KGSL_MAX_ALIGN >> 10);
flags &= ~((uint64_t) KGSL_MEMALIGN_MASK);
- flags |= (ilog2(KGSL_MAX_ALIGN) << KGSL_MEMALIGN_SHIFT) &
- KGSL_MEMALIGN_MASK;
+ flags |= (uint64_t)((ilog2(KGSL_MAX_ALIGN) <<
+ KGSL_MEMALIGN_SHIFT) &
+ KGSL_MEMALIGN_MASK);
}
/* For now only allow allocations up to 4G */
@@ -3975,7 +3979,8 @@
if (param->flags & KGSL_GPUOBJ_SET_INFO_TYPE) {
entry->memdesc.flags &= ~((uint64_t) KGSL_MEMTYPE_MASK);
- entry->memdesc.flags |= param->type << KGSL_MEMTYPE_SHIFT;
+ entry->memdesc.flags |= (uint64_t)(param->type <<
+ KGSL_MEMTYPE_SHIFT);
}
kgsl_mem_entry_put(entry);
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index d635519..938c96d 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -2600,7 +2600,7 @@
static const struct {
char *feature;
- int bit;
+ unsigned long bit;
} kgsl_iommu_features[] = {
{ "qcom,retention", KGSL_MMU_RETENTION },
{ "qcom,global_pt", KGSL_MMU_GLOBAL_PAGETABLE },
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index b3e2b6a..a9a3c94 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -67,7 +67,9 @@
"isense_clk",
"rbcpr_clk",
"iref_clk",
- "gmu_clk"
+ "gmu_clk",
+ "ahb_clk",
+ "cxo_clk"
};
static unsigned int ib_votes[KGSL_MAX_BUSLEVELS];
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 62ee597..6b22fd4 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -25,7 +25,7 @@
#define KGSL_PWR_ON 0xFFFF
-#define KGSL_MAX_CLKS 15
+#define KGSL_MAX_CLKS 17
#define KGSL_MAX_REGULATORS 2
#define KGSL_MAX_PWRLEVELS 10
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index 07a54d9..7636a42 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -927,8 +927,7 @@
&data->bin.ctxt_aware_target_pwrlevel))
data->bin.ctxt_aware_target_pwrlevel = 1;
- if ((data->bin.ctxt_aware_target_pwrlevel < 0) ||
- (data->bin.ctxt_aware_target_pwrlevel >
+ if ((data->bin.ctxt_aware_target_pwrlevel >
pwr->num_pwrlevels))
data->bin.ctxt_aware_target_pwrlevel = 1;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 10b37ae..dd41e4e 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -131,8 +131,9 @@
if (align > 32)
align = 32;
- memdesc->flags &= ~KGSL_MEMALIGN_MASK;
- memdesc->flags |= (align << KGSL_MEMALIGN_SHIFT) & KGSL_MEMALIGN_MASK;
+ memdesc->flags &= ~(uint64_t)KGSL_MEMALIGN_MASK;
+ memdesc->flags |= (uint64_t)((align << KGSL_MEMALIGN_SHIFT) &
+ KGSL_MEMALIGN_MASK);
return 0;
}
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 25eab45..e7b96f1 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -685,6 +685,13 @@
DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
},
},
+ {
+ /* Clevo P650RS, 650RP6, Sager NP8152-S, and others */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"),
+ },
+ },
{ }
};
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 261c125..7f9d9e1 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1770,3 +1770,16 @@
*id = fwspec->ids[0];
return 0;
}
+
+/*
+ * Until a formal solution for probe deferral becomes part
+ * of the iommu framework...
+ */
+int iommu_is_available(struct device *dev)
+{
+ if (!dev->bus->iommu_ops ||
+ !dev->iommu_fwspec ||
+ !dev->iommu_group)
+ return -EPROBE_DEFER;
+ return 0;
+}
diff --git a/drivers/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c
index 3060cfa..cb19cef 100644
--- a/drivers/leds/leds-qpnp-wled.c
+++ b/drivers/leds/leds-qpnp-wled.c
@@ -2264,7 +2264,7 @@
{
return platform_driver_register(&qpnp_wled_driver);
}
-module_init(qpnp_wled_init);
+subsys_initcall(qpnp_wled_init);
static void __exit qpnp_wled_exit(void)
{
diff --git a/drivers/mailbox/qti-tcs.c b/drivers/mailbox/qti-tcs.c
index dfed3cd..6d0e913 100644
--- a/drivers/mailbox/qti-tcs.c
+++ b/drivers/mailbox/qti-tcs.c
@@ -333,6 +333,20 @@
tasklet_schedule(&resp->tasklet);
}
+static inline void enable_tcs_irq(struct tcs_drv *drv, int m, bool enable)
+{
+ void __iomem *base = drv->reg_base;
+ u32 data;
+
+ /* Enable interrupts for non-ACTIVE TCS */
+ data = read_tcs_reg(base, TCS_DRV_IRQ_ENABLE, 0, 0);
+ if (enable)
+ data |= BIT(m);
+ else
+ data &= ~BIT(m);
+ write_tcs_reg(base, TCS_DRV_IRQ_ENABLE, 0, 0, data);
+}
+
/**
* tcs_irq_handler: TX Done / Recv data handler
*/
@@ -350,10 +364,9 @@
/* Know which TCSes were triggered */
irq_status = read_tcs_reg(base, TCS_DRV_IRQ_STATUS, 0, 0);
- for (m = 0; irq_status >= BIT(m); m++) {
- if (!(irq_status & BIT(m)))
+ for (m = 0; m < drv->num_tcs; m++) {
+ if (!(irq_status & (u32)BIT(m)))
continue;
-
atomic_inc(&drv->tcs_irq_count[m]);
resp = get_response(drv, m);
@@ -395,6 +408,12 @@
data = read_tcs_reg(base, TCS_DRV_CONTROL, m, 0);
data &= ~TCS_AMC_MODE_ENABLE;
write_tcs_reg(base, TCS_DRV_CONTROL, m, 0, data);
+ /*
+ * Disable interrupt for this TCS to avoid being
+ * spammed with interrupts coming when the solver
+ * sends its wake votes.
+ */
+ enable_tcs_irq(drv, m, false);
} else {
/* Clear the enable bit for the commands */
write_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0, 0);
@@ -523,9 +542,11 @@
continue;
curr_enabled = read_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0);
- for (j = 0; j < curr_enabled; j++) {
- if (!(curr_enabled & BIT(j)))
+
+ for (j = 0; j < MAX_CMDS_PER_TCS; j++) {
+ if (!(curr_enabled & (u32)BIT(j)))
continue;
+
addr = read_tcs_reg(base, TCS_DRV_CMD_ADDR, m, j);
for (k = 0; k < msg->num_payload; k++) {
if (addr == msg->payload[k].addr)
@@ -659,6 +680,9 @@
/* Mark the TCS as busy */
atomic_set(&drv->tcs_in_use[m], 1);
atomic_inc(&drv->tcs_send_count[m]);
+ /* Enable interrupt for active votes through wake TCS */
+ if (tcs->type != ACTIVE_TCS)
+ enable_tcs_irq(drv, m, true);
}
/* Write to the TCS or AMC */
@@ -902,7 +926,6 @@
u32 config, max_tcs, ncpt;
int tcs_type_count[TCS_TYPE_NR] = { 0 };
struct resource *res;
- u32 irq_mask;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
@@ -1043,14 +1066,9 @@
if (ret)
return ret;
- /*
- * Enable interrupts for AMC TCS,
- * if there are no AMC TCS, use wake TCS.
- */
- irq_mask = (drv->tcs[ACTIVE_TCS].num_tcs) ?
- drv->tcs[ACTIVE_TCS].tcs_mask :
- drv->tcs[WAKE_TCS].tcs_mask;
- write_tcs_reg(drv->reg_base, TCS_DRV_IRQ_ENABLE, 0, 0, irq_mask);
+ /* Enable interrupts for AMC TCS */
+ write_tcs_reg(drv->reg_base, TCS_DRV_IRQ_ENABLE, 0, 0,
+ drv->tcs[ACTIVE_TCS].tcs_mask);
for (i = 0; i < ARRAY_SIZE(drv->tcs_in_use); i++)
atomic_set(&drv->tcs_in_use[i], 0);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index e66f404..aac7161 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -69,6 +69,13 @@
struct dm_stats_aux stats_aux;
};
+union map_info *dm_get_rq_mapinfo(struct request *rq)
+{
+ if (rq && rq->end_io_data)
+ return &((struct dm_rq_target_io *)rq->end_io_data)->info;
+ return NULL;
+}
+
#define MINOR_ALLOCED ((void *)-1)
/*
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_subdev.c b/drivers/media/platform/msm/camera/cam_core/cam_subdev.c
index 03b18cf..429474b 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_subdev.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_subdev.c
@@ -75,7 +75,26 @@
static long cam_subdev_compat_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, unsigned long arg)
{
- return cam_subdev_ioctl(sd, cmd, compat_ptr(arg));
+ struct cam_control cmd_data;
+ int rc;
+
+ if (copy_from_user(&cmd_data, (void __user *)arg,
+ sizeof(cmd_data))) {
+ pr_err("Failed to copy from user_ptr=%pK size=%zu\n",
+ (void __user *)arg, sizeof(cmd_data));
+ return -EFAULT;
+ }
+ rc = cam_subdev_ioctl(sd, cmd, &cmd_data);
+ if (!rc) {
+ if (copy_to_user((void __user *)arg, &cmd_data,
+ sizeof(cmd_data))) {
+ pr_err("Failed to copy to user_ptr=%pK size=%zu\n",
+ (void __user *)arg, sizeof(cmd_data));
+ rc = -EFAULT;
+ }
+ }
+
+ return rc;
}
#endif
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
index 4f5bf87..ecc62c8 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
@@ -57,6 +57,48 @@
return 0;
}
+uint32_t cam_sync_util_get_group_object_state(struct sync_table_row *table,
+ uint32_t *sync_objs,
+ uint32_t num_objs)
+{
+ int i;
+ struct sync_table_row *child_row = NULL;
+ int success_count = 0;
+ int active_count = 0;
+
+ if (!table || !sync_objs)
+ return CAM_SYNC_STATE_SIGNALED_ERROR;
+
+ /*
+ * We need to arrive at the state of the merged object based on
+ * counts of error, active and success states of all children objects
+ */
+ for (i = 0; i < num_objs; i++) {
+ child_row = table + sync_objs[i];
+ switch (child_row->state) {
+ case CAM_SYNC_STATE_SIGNALED_ERROR:
+ return CAM_SYNC_STATE_SIGNALED_ERROR;
+ case CAM_SYNC_STATE_SIGNALED_SUCCESS:
+ success_count++;
+ break;
+ case CAM_SYNC_STATE_ACTIVE:
+ active_count++;
+ break;
+ default:
+ pr_err("Invalid state of child object during merge\n");
+ return CAM_SYNC_STATE_SIGNALED_ERROR;
+ }
+ }
+
+ if (active_count)
+ return CAM_SYNC_STATE_ACTIVE;
+
+ if (success_count == num_objs)
+ return CAM_SYNC_STATE_SIGNALED_SUCCESS;
+
+ return CAM_SYNC_STATE_SIGNALED_ERROR;
+}
+
int cam_sync_init_group_object(struct sync_table_row *table,
uint32_t idx,
uint32_t *sync_objs,
@@ -113,12 +155,16 @@
row->type = CAM_SYNC_TYPE_GROUP;
row->sync_id = idx;
- row->state = CAM_SYNC_STATE_ACTIVE;
+ row->state = cam_sync_util_get_group_object_state(table,
+ sync_objs, num_objs);
row->remaining = num_objs;
init_completion(&row->signaled);
INIT_LIST_HEAD(&row->callback_list);
INIT_LIST_HEAD(&row->user_payload_list);
+ if (row->state != CAM_SYNC_STATE_ACTIVE)
+ complete_all(&row->signaled);
+
spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
return 0;
}
@@ -208,6 +254,11 @@
int i;
struct sync_table_row *row = NULL;
+ if (num_objs <= 1) {
+ pr_err("Single object merge is not allowed\n");
+ return -EINVAL;
+ }
+
for (i = 0; i < num_objs; i++) {
row = sync_dev->sync_table + sync_obj[i];
spin_lock_bh(&sync_dev->row_spinlocks[sync_obj[i]]);
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index 6233b46..30fda07 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -25,6 +25,7 @@
#include <linux/msm-bus-board.h>
#include <linux/regulator/consumer.h>
#include <linux/dma-direction.h>
+#include <linux/sde_rsc.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/secure_buffer.h>
#include <asm/cacheflush.h>
@@ -318,8 +319,13 @@
if (mgr->ops_hw_pre_pmevent)
mgr->ops_hw_pre_pmevent(mgr, on);
- ret = sde_rot_enable_vreg(mgr->module_power.vreg_config,
- mgr->module_power.num_vreg, on);
+ if (mgr->rsc_client)
+ ret = sde_rsc_client_state_update(mgr->rsc_client,
+ on ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE,
+ NULL, -1);
+ else
+ ret = sde_rot_enable_vreg(mgr->module_power.vreg_config,
+ mgr->module_power.num_vreg, on);
if (ret) {
SDEROT_WARN("Rotator regulator failed to %s\n",
on ? "enable" : "disable");
@@ -2780,9 +2786,21 @@
{
int ret;
- ret = sde_rotator_get_dt_vreg_data(&pdev->dev, &mgr->module_power);
- if (ret)
+ mgr->rsc_client = sde_rsc_client_create(
+ SDE_RSC_INDEX, "sde_rotator_core", false);
+ if (IS_ERR(mgr->rsc_client)) {
+ ret = PTR_ERR(mgr->rsc_client);
+ pr_err("rsc client create returned %d\n", ret);
+ mgr->rsc_client = NULL;
return ret;
+ }
+
+ if (!mgr->rsc_client) {
+ ret = sde_rotator_get_dt_vreg_data(
+ &pdev->dev, &mgr->module_power);
+ if (ret)
+ return ret;
+ }
ret = sde_rotator_register_clk(pdev, mgr);
if (ret)
@@ -2802,9 +2820,15 @@
{
struct platform_device *pdev = mgr->pdev;
- sde_rotator_put_dt_vreg_data(&pdev->dev, &mgr->module_power);
sde_rotator_unregister_clk(mgr);
sde_rotator_bus_scale_unregister(mgr);
+
+ if (mgr->rsc_client) {
+ sde_rsc_client_destroy(mgr->rsc_client);
+ mgr->rsc_client = NULL;
+ } else {
+ sde_rotator_put_dt_vreg_data(&pdev->dev, &mgr->module_power);
+ }
}
int sde_rotator_core_init(struct sde_rot_mgr **pmgr,
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
index 13e7739..0051e96 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
@@ -373,6 +373,7 @@
* @reg_bus: register bus configuration state
* @module_power: power/clock configuration state
* @regulator_enable: true if foot switch is enabled; false otherwise
+ * @rsc_client: pointer to rsc client handle
* @res_ref_cnt: reference count of how many times resource is requested
* @rot_enable_clk_cnt: reference count of how many times clock is requested
* @rot_clk: array of rotator and periphery clocks
@@ -417,6 +418,8 @@
struct sde_module_power module_power;
bool regulator_enable;
+ struct sde_rsc_client *rsc_client;
+
int res_ref_cnt;
int rot_enable_clk_cnt;
struct sde_rot_clk *rot_clk;
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index c82db74..c5c4269 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -135,6 +135,14 @@
return msm_vidc_s_ext_ctrl((void *)vidc_inst, a);
}
+int msm_v4l2_g_ext_ctrl(struct file *file, void *fh,
+ struct v4l2_ext_controls *a)
+{
+ struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
+
+ return msm_vidc_g_ext_ctrl((void *)vidc_inst, a);
+}
+
int msm_v4l2_reqbufs(struct file *file, void *fh,
struct v4l2_requestbuffers *b)
{
@@ -250,6 +258,7 @@
.vidioc_g_ctrl = msm_v4l2_g_ctrl,
.vidioc_queryctrl = msm_v4l2_queryctrl,
.vidioc_s_ext_ctrls = msm_v4l2_s_ext_ctrl,
+ .vidioc_g_ext_ctrls = msm_v4l2_g_ext_ctrl,
.vidioc_subscribe_event = msm_v4l2_subscribe_event,
.vidioc_unsubscribe_event = msm_v4l2_unsubscribe_event,
.vidioc_decoder_cmd = msm_v4l2_decoder_cmd,
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 19a21ab..c0b6683 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1958,6 +1958,7 @@
/* Enable QP for all frame types by default */
qp.enable = 7;
qp_range.layer_id = control[i].value;
+ bitrate.layer_id = control[i].value;
i++;
while (i < ctrl->count) {
switch (control[i].id) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 8f97b15..576809b 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -28,6 +28,8 @@
static int try_get_ctrl(struct msm_vidc_inst *inst,
struct v4l2_ctrl *ctrl);
+static int msm_vidc_get_count(struct msm_vidc_inst *inst,
+ struct v4l2_ctrl *ctrl);
static int get_poll_flags(void *instance)
{
@@ -274,6 +276,40 @@
}
EXPORT_SYMBOL(msm_vidc_g_ctrl);
+int msm_vidc_g_ext_ctrl(void *instance, struct v4l2_ext_controls *control)
+{
+ struct msm_vidc_inst *inst = instance;
+ struct v4l2_ext_control *ext_control;
+ struct v4l2_ctrl ctrl;
+ int i = 0, rc = 0;
+
+ if (!inst || !control)
+ return -EINVAL;
+
+ ext_control = control->controls;
+
+ for (i = 0; i < control->count; i++) {
+ switch (ext_control[i].id) {
+ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+ case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
+ ctrl.id = ext_control[i].id;
+ ctrl.val = ext_control[i].value;
+
+ msm_vidc_get_count(inst, &ctrl);
+ ext_control->value = ctrl.val;
+ break;
+ default:
+ dprintk(VIDC_ERR,
+ "This control %x is not supported yet\n",
+ ext_control[i].id);
+ rc = -EINVAL;
+ break;
+ }
+ }
+ return rc;
+}
+EXPORT_SYMBOL(msm_vidc_g_ext_ctrl);
+
int msm_vidc_s_ext_ctrl(void *instance, struct v4l2_ext_controls *control)
{
struct msm_vidc_inst *inst = instance;
@@ -1187,6 +1223,8 @@
buf_count.buffer_type = type;
buf_count.buffer_count_actual = act_count;
buf_count.buffer_count_min_host = host_count;
+ dprintk(VIDC_DBG, "%s : Act count = %d Host count = %d\n",
+ __func__, act_count, host_count);
rc = call_hfi_op(hdev, session_set_property,
inst->session, HAL_PARAM_BUFFER_COUNT_ACTUAL, &buf_count);
if (rc)
@@ -1844,33 +1882,52 @@
static int try_get_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
{
int rc = 0;
-
- /*
- * HACK: unlock the control prior to querying the hardware. Otherwise
- * lower level code that attempts to do g_ctrl() will end up deadlocking
- * us.
- */
+ struct hal_buffer_requirements *bufreq = NULL;
+ enum hal_buffer buffer_type;
switch (ctrl->id) {
case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE:
+ case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
ctrl->val = inst->profile;
- break;
+ break;
case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL:
+ case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
ctrl->val = inst->level;
- break;
+ break;
case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
ctrl->val = inst->entropy_mode;
- break;
+ break;
case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+ if (inst->in_reconfig)
+ msm_comm_try_get_bufreqs(inst);
+
+ buffer_type = msm_comm_get_hal_output_buffer(inst);
+ bufreq = get_buff_req_buffer(inst,
+ buffer_type);
+ if (!bufreq) {
+ dprintk(VIDC_ERR,
+ "Failed to find bufreqs for buffer type = %d\n",
+ buffer_type);
+ return -EINVAL;
+ }
+ ctrl->val = bufreq->buffer_count_min_host;
+ break;
case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
- rc = msm_vidc_get_count(inst, ctrl);
+ bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT);
+ if (!bufreq) {
+ dprintk(VIDC_ERR,
+ "Failed to find bufreqs for buffer type = %d\n",
+ HAL_BUFFER_INPUT);
+ return -EINVAL;
+ }
+ ctrl->val = bufreq->buffer_count_min_host;
break;
default:
/*
@@ -1878,7 +1935,7 @@
* modify ctrl->value
*/
break;
-}
+ }
return rc;
}
@@ -2037,6 +2094,7 @@
goto fail_init;
}
+ msm_dcvs_try_enable(inst);
if (msm_vidc_check_for_inst_overload(core)) {
dprintk(VIDC_ERR,
"Instance count reached Max limit, rejecting session");
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index d4562ce..0efe93b 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -4094,9 +4094,8 @@
dprintk(VIDC_DBG, "%15s %8s %8s %8s %8s\n",
"buffer type", "count", "mincount_host", "mincount_fw", "size");
for (i = 0; i < HAL_BUFFER_MAX; i++) {
- struct hal_buffer_requirements req = hprop.buf_req.buffer[i];
+ struct hal_buffer_requirements req = inst->buff_req.buffer[i];
- inst->buff_req.buffer[i] = req;
if (req.buffer_type != HAL_BUFFER_NONE) {
dprintk(VIDC_DBG, "%15s %8d %8d %8d %8d\n",
get_buffer_name(req.buffer_type),
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 2afa1eb..f37d64c 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -45,27 +45,36 @@
compat_caddr_t bitmap;
};
-static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+static int get_v4l2_window32(struct v4l2_window __user *kp,
+ struct v4l2_window32 __user *up)
{
+ u32 clipcount = 0;
+
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
- copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
- get_user(kp->field, &up->field) ||
- get_user(kp->chromakey, &up->chromakey) ||
- get_user(kp->clipcount, &up->clipcount))
+ !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_window)) ||
+ copy_in_user(&kp->w, &up->w, sizeof(up->w)) ||
+ copy_in_user(&kp->field, &up->field, sizeof(up->field)) ||
+ copy_in_user(&kp->chromakey, &up->chromakey,
+ sizeof(up->chromakey)) ||
+ copy_in_user(&kp->clipcount, &up->clipcount,
+ sizeof(up->clipcount)))
return -EFAULT;
- if (kp->clipcount > 2048)
+ if (get_user(clipcount, &kp->clipcount))
+ return -EFAULT;
+ if (clipcount > 2048)
return -EINVAL;
- if (kp->clipcount) {
+ if (clipcount) {
struct v4l2_clip32 __user *uclips;
struct v4l2_clip __user *kclips;
- int n = kp->clipcount;
+ int n = clipcount;
compat_caddr_t p;
if (get_user(p, &up->clips))
return -EFAULT;
uclips = compat_ptr(p);
kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
- kp->clips = kclips;
+ if (put_user(kclips, &kp->clips))
+ return -EFAULT;
while (--n >= 0) {
if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
return -EFAULT;
@@ -74,89 +83,106 @@
uclips += 1;
kclips += 1;
}
- } else
- kp->clips = NULL;
- return 0;
-}
-
-static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
-{
- if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) ||
- put_user(kp->field, &up->field) ||
- put_user(kp->chromakey, &up->chromakey) ||
- put_user(kp->clipcount, &up->clipcount))
+ } else {
+ if (put_user(NULL, &kp->clips))
return -EFAULT;
+ }
return 0;
}
-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
+static int put_v4l2_window32(struct v4l2_window __user *kp,
+ struct v4l2_window32 __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
+ if (copy_in_user(&up->w, &kp->w, sizeof(up->w)) ||
+ copy_in_user(&up->field, &kp->field, sizeof(up->field)) ||
+ copy_in_user(&up->chromakey, &kp->chromakey,
+ sizeof(up->chromakey)) ||
+ copy_in_user(&up->clipcount, &kp->clipcount,
+ sizeof(up->clipcount)))
return -EFAULT;
return 0;
}
-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
+static inline int get_v4l2_pix_format(struct v4l2_pix_format __user *kp,
+ struct v4l2_pix_format __user *up)
+{
+ if (copy_in_user(kp, up, sizeof(struct v4l2_pix_format)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int get_v4l2_pix_format_mplane(
+ struct v4l2_pix_format_mplane __user *kp,
struct v4l2_pix_format_mplane __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
+ if (copy_in_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
+static inline int put_v4l2_pix_format(struct v4l2_pix_format __user *kp,
+ struct v4l2_pix_format __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_pix_format)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
+static inline int put_v4l2_pix_format_mplane(
+ struct v4l2_pix_format_mplane __user *kp,
struct v4l2_pix_format_mplane __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
return -EFAULT;
return 0;
}
-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
+static inline int get_v4l2_vbi_format(struct v4l2_vbi_format __user *kp,
+ struct v4l2_vbi_format __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
+ if (copy_in_user(kp, up, sizeof(struct v4l2_vbi_format)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
+static inline int put_v4l2_vbi_format(struct v4l2_vbi_format __user *kp,
+ struct v4l2_vbi_format __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_vbi_format)))
return -EFAULT;
return 0;
}
-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
+static inline int get_v4l2_sliced_vbi_format(
+ struct v4l2_sliced_vbi_format __user *kp,
+ struct v4l2_sliced_vbi_format __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
+ if (copy_in_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
+static inline int put_v4l2_sliced_vbi_format(
+ struct v4l2_sliced_vbi_format __user *kp,
+ struct v4l2_sliced_vbi_format __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
return -EFAULT;
return 0;
}
-static inline int get_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up)
+static inline int get_v4l2_sdr_format(struct v4l2_sdr_format __user *kp,
+ struct v4l2_sdr_format __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_sdr_format)))
+ if (copy_in_user(kp, up, sizeof(struct v4l2_sdr_format)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up)
+static inline int put_v4l2_sdr_format(struct v4l2_sdr_format __user *kp,
+ struct v4l2_sdr_format __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_sdr_format)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_sdr_format)))
return -EFAULT;
return 0;
}
@@ -191,12 +217,17 @@
__u32 reserved[8];
};
-static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int __get_v4l2_format32(struct v4l2_format __user *kp,
+ struct v4l2_format32 __user *up)
{
- if (get_user(kp->type, &up->type))
+ u32 type;
+
+ if (copy_in_user(&kp->type, &up->type, sizeof(up->type)))
return -EFAULT;
- switch (kp->type) {
+ if (get_user(type, &kp->type))
+ return -EFAULT;
+ switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
@@ -223,27 +254,39 @@
}
}
-static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int get_v4l2_format32(struct v4l2_format __user *kp,
+ struct v4l2_format32 __user *up)
{
- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
+ !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_format)))
return -EFAULT;
return __get_v4l2_format32(kp, up);
}
-static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+static int get_v4l2_create32(struct v4l2_create_buffers __user *kp,
+ struct v4l2_create_buffers32 __user *up)
{
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
- copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format)))
+ !access_ok(VERIFY_WRITE, kp,
+ sizeof(struct v4l2_create_buffers)) ||
+ copy_in_user(kp, up,
+ offsetof(struct v4l2_create_buffers32, format)))
return -EFAULT;
return __get_v4l2_format32(&kp->format, &up->format);
}
-static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int __put_v4l2_format32(struct v4l2_format __user *kp,
+ struct v4l2_format32 __user *up)
{
- if (put_user(kp->type, &up->type))
+ u32 type;
+
+ if (copy_in_user(&up->type, &kp->type, sizeof(up->type)))
return -EFAULT;
- switch (kp->type) {
+ if (get_user(type, &kp->type))
+ return -EFAULT;
+
+ switch (type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
@@ -270,18 +313,24 @@
}
}
-static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int put_v4l2_format32(struct v4l2_format __user *kp,
+ struct v4l2_format32 __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)))
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+ !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_format)))
return -EFAULT;
return __put_v4l2_format32(kp, up);
}
-static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+static int put_v4l2_create32(struct v4l2_create_buffers __user *kp,
+ struct v4l2_create_buffers32 __user *up)
{
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
- copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) ||
- copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
+ !access_ok(VERIFY_READ, kp,
+ sizeof(struct v4l2_create_buffers)) ||
+ copy_in_user(up, kp,
+ offsetof(struct v4l2_create_buffers32, format)) ||
+ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
return -EFAULT;
return __put_v4l2_format32(&kp->format, &up->format);
}
@@ -295,24 +344,30 @@
__u32 reserved[4];
};
-static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+static int get_v4l2_standard32(struct v4l2_standard __user *kp,
+ struct v4l2_standard32 __user *up)
{
/* other fields are not set by the user, nor used by the driver */
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
- get_user(kp->index, &up->index))
+ !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_standard)) ||
+ copy_in_user(&kp->index, &up->index, sizeof(up->index)))
return -EFAULT;
return 0;
}
-static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+static int put_v4l2_standard32(struct v4l2_standard __user *kp,
+ struct v4l2_standard32 __user *up)
{
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
- put_user(kp->index, &up->index) ||
- put_user(kp->id, &up->id) ||
- copy_to_user(up->name, kp->name, 24) ||
- copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
- put_user(kp->framelines, &up->framelines) ||
- copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+ !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_standard)) ||
+ copy_in_user(&up->index, &kp->index, sizeof(up->index)) ||
+ copy_in_user(&up->id, &kp->id, sizeof(up->id)) ||
+ copy_in_user(up->name, kp->name, 24) ||
+ copy_in_user(&up->frameperiod, &kp->frameperiod,
+ sizeof(up->frameperiod)) ||
+ copy_in_user(&up->framelines, &kp->framelines,
+ sizeof(up->framelines)) ||
+ copy_in_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
return -EFAULT;
return 0;
}
@@ -410,34 +465,48 @@
return 0;
}
-static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
+static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
+ struct v4l2_buffer32 __user *up)
{
struct v4l2_plane32 __user *uplane32;
struct v4l2_plane __user *uplane;
compat_caddr_t p;
int num_planes;
+ struct timeval time;
+ u32 plane_count, memory, type;
int ret;
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
- get_user(kp->index, &up->index) ||
- get_user(kp->type, &up->type) ||
- get_user(kp->flags, &up->flags) ||
- get_user(kp->memory, &up->memory) ||
- get_user(kp->length, &up->length))
+ !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_buffer)) ||
+ copy_in_user(&kp->index, &up->index, sizeof(up->index)) ||
+ copy_in_user(&kp->type, &up->type, sizeof(up->type)) ||
+ copy_in_user(&kp->flags, &up->flags, sizeof(up->flags)) ||
+ copy_in_user(&kp->memory, &up->memory, sizeof(up->memory)) ||
+ copy_in_user(&kp->length, &up->length, sizeof(up->length)))
return -EFAULT;
- if (V4L2_TYPE_IS_OUTPUT(kp->type))
- if (get_user(kp->bytesused, &up->bytesused) ||
- get_user(kp->field, &up->field) ||
- get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
- get_user(kp->timestamp.tv_usec,
- &up->timestamp.tv_usec))
+ if (get_user(type, &kp->type))
+ return -EFAULT;
+ if (V4L2_TYPE_IS_OUTPUT(type))
+ if (copy_in_user(&kp->bytesused, &up->bytesused,
+ sizeof(up->bytesused)) ||
+ copy_in_user(&kp->field, &up->field,
+ sizeof(up->field)) ||
+ get_user(time.tv_sec, &up->timestamp.tv_sec) ||
+ get_user(time.tv_usec, &up->timestamp.tv_usec) ||
+ put_user(time.tv_sec, &kp->timestamp.tv_sec) ||
+ put_user(time.tv_usec, &kp->timestamp.tv_usec))
return -EFAULT;
- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
- num_planes = kp->length;
+ if (get_user(memory, &kp->memory))
+ return -EFAULT;
+ if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+ if (get_user(plane_count, &kp->length))
+ return -EFAULT;
+ num_planes = plane_count;
if (num_planes == 0) {
- kp->m.planes = NULL;
+ if (put_user(NULL, &kp->m.planes))
+ return -EFAULT;
/* num_planes == 0 is legal, e.g. when userspace doesn't
* need planes array on DQBUF*/
return 0;
@@ -455,37 +524,43 @@
* by passing a very big num_planes value */
uplane = compat_alloc_user_space(num_planes *
sizeof(struct v4l2_plane));
- kp->m.planes = (__force struct v4l2_plane *)uplane;
+ if (put_user(uplane, &kp->m.planes))
+ return -EFAULT;
while (--num_planes >= 0) {
- ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
+ ret = get_v4l2_plane32(uplane, uplane32, memory);
if (ret)
return ret;
++uplane;
++uplane32;
}
} else {
- switch (kp->memory) {
+ switch (memory) {
case V4L2_MEMORY_MMAP:
- if (get_user(kp->m.offset, &up->m.offset))
+ if (copy_in_user(&kp->m.offset, &up->m.offset,
+ sizeof(up->m.offset)))
return -EFAULT;
break;
case V4L2_MEMORY_USERPTR:
{
compat_long_t tmp;
+ unsigned long userptr;
if (get_user(tmp, &up->m.userptr))
return -EFAULT;
- kp->m.userptr = (unsigned long)compat_ptr(tmp);
+ userptr = (unsigned long)compat_ptr(tmp);
+ put_user(userptr, &kp->m.userptr);
}
break;
case V4L2_MEMORY_OVERLAY:
- if (get_user(kp->m.offset, &up->m.offset))
+ if (copy_in_user(&kp->m.offset, &up->m.offset,
+ sizeof(up->m.offset)))
return -EFAULT;
break;
case V4L2_MEMORY_DMABUF:
- if (get_user(kp->m.fd, &up->m.fd))
+ if (copy_in_user(&kp->m.fd, &up->m.fd,
+ sizeof(up->m.fd)))
return -EFAULT;
break;
}
@@ -494,65 +569,86 @@
return 0;
}
-static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
+static int put_v4l2_buffer32(struct v4l2_buffer __user *kp,
+ struct v4l2_buffer32 __user *up)
{
struct v4l2_plane32 __user *uplane32;
struct v4l2_plane __user *uplane;
compat_caddr_t p;
int num_planes;
int ret;
+ struct timeval time;
+ u32 memory, type, length;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
- put_user(kp->index, &up->index) ||
- put_user(kp->type, &up->type) ||
- put_user(kp->flags, &up->flags) ||
- put_user(kp->memory, &up->memory))
- return -EFAULT;
+ !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_buffer)) ||
+ copy_in_user(&up->index, &kp->index, sizeof(up->index)) ||
+ copy_in_user(&up->type, &kp->type, sizeof(up->type)) ||
+ copy_in_user(&up->flags, &kp->flags, sizeof(up->flags)) ||
+ copy_in_user(&up->memory, &kp->memory, sizeof(up->memory)))
+ return -EFAULT;
- if (put_user(kp->bytesused, &up->bytesused) ||
- put_user(kp->field, &up->field) ||
- put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
- put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
- copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
- put_user(kp->sequence, &up->sequence) ||
- put_user(kp->reserved2, &up->reserved2) ||
- put_user(kp->reserved, &up->reserved) ||
- put_user(kp->length, &up->length))
- return -EFAULT;
+ if (copy_in_user(&up->bytesused, &kp->bytesused,
+ sizeof(up->bytesused)) ||
+ copy_in_user(&up->field, &kp->field, sizeof(up->field)) ||
+ get_user(time.tv_sec, &kp->timestamp.tv_sec) ||
+ get_user(time.tv_usec, &kp->timestamp.tv_usec) ||
+ put_user(time.tv_sec, &up->timestamp.tv_sec) ||
+ put_user(time.tv_usec, &up->timestamp.tv_usec) ||
+ copy_in_user(&up->timecode, &kp->timecode,
+ sizeof(struct v4l2_timecode)) ||
+ copy_in_user(&up->sequence, &kp->sequence,
+ sizeof(up->sequence)) ||
+ copy_in_user(&up->reserved2, &kp->reserved2,
+ sizeof(up->reserved2)) ||
+ copy_in_user(&up->reserved, &kp->reserved,
+ sizeof(up->reserved)) ||
+ copy_in_user(&up->length, &kp->length, sizeof(up->length)))
+ return -EFAULT;
- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
- num_planes = kp->length;
+ if (get_user(type, &kp->type) ||
+ get_user(memory, &kp->memory) ||
+ get_user(length, &kp->length))
+ return -EINVAL;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+ num_planes = length;
if (num_planes == 0)
return 0;
- uplane = (__force struct v4l2_plane __user *)kp->m.planes;
+ if (get_user(uplane, &kp->m.planes))
+ return -EFAULT;
if (get_user(p, &up->m.planes))
return -EFAULT;
uplane32 = compat_ptr(p);
while (--num_planes >= 0) {
- ret = put_v4l2_plane32(uplane, uplane32, kp->memory);
+ ret = put_v4l2_plane32(uplane, uplane32, memory);
if (ret)
return ret;
++uplane;
++uplane32;
}
} else {
- switch (kp->memory) {
+ switch (memory) {
case V4L2_MEMORY_MMAP:
- if (put_user(kp->m.offset, &up->m.offset))
+ if (copy_in_user(&up->m.offset, &kp->m.offset,
+ sizeof(up->m.offset)))
return -EFAULT;
break;
case V4L2_MEMORY_USERPTR:
- if (put_user(kp->m.userptr, &up->m.userptr))
+ if (copy_in_user(&up->m.userptr, &kp->m.userptr,
+ sizeof(up->m.userptr)))
return -EFAULT;
break;
case V4L2_MEMORY_OVERLAY:
- if (put_user(kp->m.offset, &up->m.offset))
+ if (copy_in_user(&up->m.offset, &kp->m.offset,
+ sizeof(up->m.offset)))
return -EFAULT;
break;
case V4L2_MEMORY_DMABUF:
- if (put_user(kp->m.fd, &up->m.fd))
+ if (copy_in_user(&up->m.fd, &kp->m.fd,
+ sizeof(up->m.fd)))
return -EFAULT;
break;
}
@@ -577,29 +673,39 @@
} fmt;
};
-static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
+static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
+ struct v4l2_framebuffer32 __user *up)
{
u32 tmp;
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
+ !access_ok(VERIFY_WRITE, kp,
+ sizeof(struct v4l2_framebuffer)) ||
get_user(tmp, &up->base) ||
- get_user(kp->capability, &up->capability) ||
- get_user(kp->flags, &up->flags) ||
- copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
+ put_user(compat_ptr(tmp), &kp->base) ||
+ copy_in_user(&kp->capability, &up->capability,
+ sizeof(up->capability)) ||
+ copy_in_user(&kp->flags, &up->flags, sizeof(up->flags)) ||
+ copy_in_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
return -EFAULT;
- kp->base = (__force void *)compat_ptr(tmp);
+
return 0;
}
-static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
+static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
+ struct v4l2_framebuffer32 __user *up)
{
- u32 tmp = (u32)((unsigned long)kp->base);
+ unsigned long base;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
- put_user(tmp, &up->base) ||
- put_user(kp->capability, &up->capability) ||
- put_user(kp->flags, &up->flags) ||
- copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
+ !access_ok(VERIFY_READ, kp,
+ sizeof(struct v4l2_framebuffer)) ||
+ copy_from_user(&base, &kp->base, sizeof(base)) ||
+ put_user((u32)base, &up->base) ||
+ copy_in_user(&up->capability, &kp->capability,
+ sizeof(up->capability)) ||
+ copy_in_user(&up->flags, &kp->flags, sizeof(up->flags)) ||
+ copy_in_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
return -EFAULT;
return 0;
}
@@ -617,16 +723,18 @@
/* The 64-bit v4l2_input struct has extra padding at the end of the struct.
Otherwise it is identical to the 32-bit version. */
-static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
+static inline int get_v4l2_input32(struct v4l2_input __user *kp,
+ struct v4l2_input32 __user *up)
{
- if (copy_from_user(kp, up, sizeof(struct v4l2_input32)))
+ if (copy_in_user(kp, up, sizeof(struct v4l2_input32)))
return -EFAULT;
return 0;
}
-static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
+static inline int put_v4l2_input32(struct v4l2_input __user *kp,
+ struct v4l2_input32 __user *up)
{
- if (copy_to_user(up, kp, sizeof(struct v4l2_input32)))
+ if (copy_in_user(up, kp, sizeof(struct v4l2_input32)))
return -EFAULT;
return 0;
}
@@ -667,23 +775,33 @@
}
}
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
+static int get_v4l2_ext_controls32(struct v4l2_ext_controls __user *kp,
+ struct v4l2_ext_controls32 __user *up)
{
struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
int n;
compat_caddr_t p;
+ u32 count;
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
- get_user(kp->which, &up->which) ||
- get_user(kp->count, &up->count) ||
- get_user(kp->error_idx, &up->error_idx) ||
- copy_from_user(kp->reserved, up->reserved,
- sizeof(kp->reserved)))
+ !access_ok(VERIFY_WRITE, kp,
+ sizeof(struct v4l2_ext_controls)) ||
+ copy_in_user(&kp->which, &up->which,
+ sizeof(up->which)) ||
+ copy_in_user(&kp->count, &up->count, sizeof(up->count)) ||
+ copy_in_user(&kp->error_idx, &up->error_idx,
+ sizeof(up->error_idx)) ||
+ copy_in_user(kp->reserved, up->reserved,
+ sizeof(up->reserved)))
return -EFAULT;
- n = kp->count;
+
+ if (get_user(count, &kp->count))
+ return -EFAULT;
+ n = count;
if (n == 0) {
- kp->controls = NULL;
+ if (put_user(NULL, &kp->controls))
+ return -EINVAL;
return 0;
}
if (get_user(p, &up->controls))
@@ -693,7 +811,9 @@
n * sizeof(struct v4l2_ext_control32)))
return -EFAULT;
kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
- kp->controls = (__force struct v4l2_ext_control *)kcontrols;
+ if (put_user(kcontrols, &kp->controls))
+ return -EFAULT;
+
while (--n >= 0) {
u32 id;
@@ -716,23 +836,33 @@
return 0;
}
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct v4l2_ext_controls __user *kp,
+ struct v4l2_ext_controls32 __user *up)
{
struct v4l2_ext_control32 __user *ucontrols;
- struct v4l2_ext_control __user *kcontrols =
- (__force struct v4l2_ext_control __user *)kp->controls;
- int n = kp->count;
+ struct v4l2_ext_control __user *kcontrols;
+ int n;
+ u32 count;
compat_caddr_t p;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
- put_user(kp->which, &up->which) ||
- put_user(kp->count, &up->count) ||
- put_user(kp->error_idx, &up->error_idx) ||
- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+ !access_ok(VERIFY_READ, kp,
+ sizeof(struct v4l2_ext_controls)) ||
+ copy_in_user(&up->which, &kp->which,
+ sizeof(up->which)) ||
+ copy_in_user(&up->count, &kp->count,
+ sizeof(up->count)) ||
+ copy_in_user(&up->error_idx, &kp->error_idx,
+ sizeof(up->error_idx)) ||
+ copy_in_user(up->reserved, kp->reserved,
+ sizeof(up->reserved)) ||
+ get_user(count, &kp->count) ||
+ get_user(kcontrols, &kp->controls))
return -EFAULT;
- if (!kp->count)
+ if (!count)
return 0;
+ n = count;
if (get_user(p, &up->controls))
return -EFAULT;
ucontrols = compat_ptr(p);
@@ -772,16 +902,22 @@
__u32 reserved[8];
};
-static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up)
+static int put_v4l2_event32(struct v4l2_event __user *kp,
+ struct v4l2_event32 __user *up)
{
+ struct timespec ts;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) ||
- put_user(kp->type, &up->type) ||
- copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
- put_user(kp->pending, &up->pending) ||
- put_user(kp->sequence, &up->sequence) ||
- compat_put_timespec(&kp->timestamp, &up->timestamp) ||
- put_user(kp->id, &up->id) ||
- copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
+ !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_event)) ||
+ copy_in_user(&up->type, &kp->type, sizeof(up->type)) ||
+ copy_in_user(&up->u, &kp->u, sizeof(up->u)) ||
+ copy_in_user(&up->pending, &kp->pending,
+ sizeof(up->pending)) ||
+ copy_in_user(&up->sequence, &kp->sequence,
+ sizeof(up->sequence)) ||
+ copy_from_user(&ts, &kp->timestamp, sizeof(ts)) ||
+ compat_put_timespec(&ts, &up->timestamp) ||
+ copy_in_user(&up->id, &kp->id, sizeof(up->id)) ||
+ copy_in_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
return -EFAULT;
return 0;
}
@@ -794,31 +930,39 @@
compat_caddr_t edid;
};
-static int get_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
+static int get_v4l2_edid32(struct v4l2_edid __user *kp,
+ struct v4l2_edid32 __user *up)
{
u32 tmp;
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_edid32)) ||
- get_user(kp->pad, &up->pad) ||
- get_user(kp->start_block, &up->start_block) ||
- get_user(kp->blocks, &up->blocks) ||
+ !access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_edid)) ||
+ copy_in_user(&kp->pad, &up->pad, sizeof(up->pad)) ||
+ copy_in_user(&kp->start_block, &up->start_block,
+ sizeof(up->start_block)) ||
+ copy_in_user(&kp->blocks, &up->blocks, sizeof(up->blocks)) ||
get_user(tmp, &up->edid) ||
- copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+ put_user(compat_ptr(tmp), &kp->edid) ||
+ copy_in_user(kp->reserved, up->reserved,
+ sizeof(kp->reserved)))
return -EFAULT;
- kp->edid = (__force u8 *)compat_ptr(tmp);
return 0;
}
-static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
+static int put_v4l2_edid32(struct v4l2_edid __user *kp,
+ struct v4l2_edid32 __user *up)
{
- u32 tmp = (u32)((unsigned long)kp->edid);
+ unsigned long ptr;
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_edid32)) ||
- put_user(kp->pad, &up->pad) ||
- put_user(kp->start_block, &up->start_block) ||
- put_user(kp->blocks, &up->blocks) ||
- put_user(tmp, &up->edid) ||
- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+ !access_ok(VERIFY_READ, kp, sizeof(struct v4l2_edid)) ||
+ copy_in_user(&up->pad, &kp->pad, sizeof(up->pad)) ||
+ copy_in_user(&up->start_block, &kp->start_block,
+ sizeof(up->start_block)) ||
+ copy_in_user(&up->blocks, &kp->blocks, sizeof(up->blocks)) ||
+ copy_from_user(&ptr, &kp->edid, sizeof(ptr)) ||
+ put_user((u32)ptr, &up->edid) ||
+ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
return -EFAULT;
return 0;
}
@@ -865,11 +1009,16 @@
struct v4l2_edid v2edid;
unsigned long vx;
int vi;
- } karg;
+ } *karg;
void __user *up = compat_ptr(arg);
int compatible_arg = 1;
long err = 0;
+ karg = compat_alloc_user_space(sizeof(*karg));
+ if (karg == NULL) {
+ return -EFAULT;
+ }
+
/* First, convert the command. */
switch (cmd) {
case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
@@ -905,7 +1054,8 @@
case VIDIOC_STREAMOFF:
case VIDIOC_S_INPUT:
case VIDIOC_S_OUTPUT:
- err = get_user(karg.vi, (s32 __user *)up);
+ err = copy_in_user(&karg->vi, (s32 __user *)up,
+ sizeof(karg->vi));
compatible_arg = 0;
break;
@@ -916,19 +1066,19 @@
case VIDIOC_G_EDID:
case VIDIOC_S_EDID:
- err = get_v4l2_edid32(&karg.v2edid, up);
+ err = get_v4l2_edid32(&karg->v2edid, up);
compatible_arg = 0;
break;
case VIDIOC_G_FMT:
case VIDIOC_S_FMT:
case VIDIOC_TRY_FMT:
- err = get_v4l2_format32(&karg.v2f, up);
+ err = get_v4l2_format32(&karg->v2f, up);
compatible_arg = 0;
break;
case VIDIOC_CREATE_BUFS:
- err = get_v4l2_create32(&karg.v2crt, up);
+ err = get_v4l2_create32(&karg->v2crt, up);
compatible_arg = 0;
break;
@@ -936,12 +1086,12 @@
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
- err = get_v4l2_buffer32(&karg.v2b, up);
+ err = get_v4l2_buffer32(&karg->v2b, up);
compatible_arg = 0;
break;
case VIDIOC_S_FBUF:
- err = get_v4l2_framebuffer32(&karg.v2fb, up);
+ err = get_v4l2_framebuffer32(&karg->v2fb, up);
compatible_arg = 0;
break;
@@ -950,19 +1100,19 @@
break;
case VIDIOC_ENUMSTD:
- err = get_v4l2_standard32(&karg.v2s, up);
+ err = get_v4l2_standard32(&karg->v2s, up);
compatible_arg = 0;
break;
case VIDIOC_ENUMINPUT:
- err = get_v4l2_input32(&karg.v2i, up);
+ err = get_v4l2_input32(&karg->v2i, up);
compatible_arg = 0;
break;
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
- err = get_v4l2_ext_controls32(&karg.v2ecs, up);
+ err = get_v4l2_ext_controls32(&karg->v2ecs, up);
compatible_arg = 0;
break;
case VIDIOC_DQEVENT:
@@ -975,11 +1125,7 @@
if (compatible_arg)
err = native_ioctl(file, cmd, (unsigned long)up);
else {
- mm_segment_t old_fs = get_fs();
-
- set_fs(KERNEL_DS);
- err = native_ioctl(file, cmd, (unsigned long)&karg);
- set_fs(old_fs);
+ err = native_ioctl(file, cmd, (unsigned long)karg);
}
/* Special case: even after an error we need to put the
@@ -989,7 +1135,7 @@
case VIDIOC_G_EXT_CTRLS:
case VIDIOC_S_EXT_CTRLS:
case VIDIOC_TRY_EXT_CTRLS:
- if (put_v4l2_ext_controls32(&karg.v2ecs, up))
+ if (put_v4l2_ext_controls32(&karg->v2ecs, up))
err = -EFAULT;
break;
}
@@ -1001,44 +1147,44 @@
case VIDIOC_S_OUTPUT:
case VIDIOC_G_INPUT:
case VIDIOC_G_OUTPUT:
- err = put_user(((s32)karg.vi), (s32 __user *)up);
+ err = copy_in_user(up, &karg->vi, sizeof(s32));
break;
case VIDIOC_G_FBUF:
- err = put_v4l2_framebuffer32(&karg.v2fb, up);
+ err = put_v4l2_framebuffer32(&karg->v2fb, up);
break;
case VIDIOC_DQEVENT:
- err = put_v4l2_event32(&karg.v2ev, up);
+ err = put_v4l2_event32(&karg->v2ev, up);
break;
case VIDIOC_G_EDID:
case VIDIOC_S_EDID:
- err = put_v4l2_edid32(&karg.v2edid, up);
+ err = put_v4l2_edid32(&karg->v2edid, up);
break;
case VIDIOC_G_FMT:
case VIDIOC_S_FMT:
case VIDIOC_TRY_FMT:
- err = put_v4l2_format32(&karg.v2f, up);
+ err = put_v4l2_format32(&karg->v2f, up);
break;
case VIDIOC_CREATE_BUFS:
- err = put_v4l2_create32(&karg.v2crt, up);
+ err = put_v4l2_create32(&karg->v2crt, up);
break;
case VIDIOC_QUERYBUF:
case VIDIOC_QBUF:
case VIDIOC_DQBUF:
- err = put_v4l2_buffer32(&karg.v2b, up);
+ err = put_v4l2_buffer32(&karg->v2b, up);
break;
case VIDIOC_ENUMSTD:
- err = put_v4l2_standard32(&karg.v2s, up);
+ err = put_v4l2_standard32(&karg->v2s, up);
break;
case VIDIOC_ENUMINPUT:
- err = put_v4l2_input32(&karg.v2i, up);
+ err = put_v4l2_input32(&karg->v2i, up);
break;
}
return err;
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index adc2147..0898414 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -337,6 +337,7 @@
"4.2",
"5",
"5.1",
+ "5.2",
NULL,
};
static const char * const h264_loop_filter[] = {
@@ -363,6 +364,7 @@
"Scalable High Intra",
"Stereo High",
"Multiview High",
+ "Constrained High",
NULL,
};
static const char * const vui_sar_idc[] = {
diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c
index 3bc7d4e..127a052 100644
--- a/drivers/misc/uid_sys_stats.c
+++ b/drivers/misc/uid_sys_stats.c
@@ -96,9 +96,11 @@
{
struct uid_entry *uid_entry;
struct task_struct *task, *temp;
+ struct user_namespace *user_ns = current_user_ns();
cputime_t utime;
cputime_t stime;
unsigned long bkt;
+ uid_t uid;
rt_mutex_lock(&uid_lock);
@@ -109,14 +111,13 @@
read_lock(&tasklist_lock);
do_each_thread(temp, task) {
- uid_entry = find_or_register_uid(from_kuid_munged(
- current_user_ns(), task_uid(task)));
+ uid = from_kuid_munged(user_ns, task_uid(task));
+ uid_entry = find_or_register_uid(uid);
if (!uid_entry) {
read_unlock(&tasklist_lock);
rt_mutex_unlock(&uid_lock);
pr_err("%s: failed to find the uid_entry for uid %d\n",
- __func__, from_kuid_munged(current_user_ns(),
- task_uid(task)));
+ __func__, uid);
return -ENOMEM;
}
task_cputime_adjusted(task, &utime, &stime);
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index a0dabd4..7ab24c5 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -740,13 +740,18 @@
static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
{
struct gs_can *dev = netdev_priv(netdev);
- struct gs_identify_mode imode;
+ struct gs_identify_mode *imode;
int rc;
+ imode = kmalloc(sizeof(*imode), GFP_KERNEL);
+
+ if (!imode)
+ return -ENOMEM;
+
if (do_identify)
- imode.mode = GS_CAN_IDENTIFY_ON;
+ imode->mode = GS_CAN_IDENTIFY_ON;
else
- imode.mode = GS_CAN_IDENTIFY_OFF;
+ imode->mode = GS_CAN_IDENTIFY_OFF;
rc = usb_control_msg(interface_to_usbdev(dev->iface),
usb_sndctrlpipe(interface_to_usbdev(dev->iface),
@@ -756,10 +761,12 @@
USB_RECIP_INTERFACE,
dev->channel,
0,
- &imode,
- sizeof(imode),
+ imode,
+ sizeof(*imode),
100);
+ kfree(imode);
+
return (rc > 0) ? 0 : rc;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 81d8e3b..21ce0b7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -82,7 +82,7 @@
#define MLX5E_VALID_NUM_MTTS(num_mtts) (MLX5_MTT_OCTW(num_mtts) <= U16_MAX)
#define MLX5_UMR_ALIGN (2048)
-#define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD (128)
+#define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD (256)
#define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ (64 * 1024)
#define MLX5E_DEFAULT_LRO_TIMEOUT 32
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
index 90e81ae..e034dbc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
@@ -563,6 +563,7 @@
int idx = 0;
int err = 0;
+ info->data = MAX_NUM_OF_ETHTOOL_RULES;
while ((!err || err == -ENOENT) && idx < info->rule_cnt) {
err = mlx5e_ethtool_get_flow(priv, info, location);
if (!err)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c
index 5595724..b5d5519 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c
@@ -294,7 +294,7 @@
struct netdev_notifier_changeupper_info *info)
{
struct net_device *upper = info->upper_dev, *ndev_tmp;
- struct netdev_lag_upper_info *lag_upper_info;
+ struct netdev_lag_upper_info *lag_upper_info = NULL;
bool is_bonded;
int bond_status = 0;
int num_slaves = 0;
@@ -303,7 +303,8 @@
if (!netif_is_lag_master(upper))
return 0;
- lag_upper_info = info->upper_info;
+ if (info->linking)
+ lag_upper_info = info->upper_info;
/* The event may still be of interest if the slave does not belong to
* us, but is enslaved to a master which has one or more of our netdevs
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 7a196a0..d776db7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -966,7 +966,7 @@
if (err) {
dev_err(&dev->pdev->dev, "Firmware over %d MS in initializing state, aborting\n",
FW_INIT_TIMEOUT_MILI);
- goto out_err;
+ goto err_cmd_cleanup;
}
err = mlx5_core_enable_hca(dev, 0);
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 1a92de7..a2d218b 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1059,12 +1059,70 @@
.get_mdio_data = sh_get_mdio,
};
+/* free Tx skb function */
+static int sh_eth_tx_free(struct net_device *ndev, bool sent_only)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ struct sh_eth_txdesc *txdesc;
+ int free_num = 0;
+ int entry;
+ bool sent;
+
+ for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
+ entry = mdp->dirty_tx % mdp->num_tx_ring;
+ txdesc = &mdp->tx_ring[entry];
+ sent = !(txdesc->status & cpu_to_le32(TD_TACT));
+ if (sent_only && !sent)
+ break;
+ /* TACT bit must be checked before all the following reads */
+ dma_rmb();
+ netif_info(mdp, tx_done, ndev,
+ "tx entry %d status 0x%08x\n",
+ entry, le32_to_cpu(txdesc->status));
+ /* Free the original skb. */
+ if (mdp->tx_skbuff[entry]) {
+ dma_unmap_single(&ndev->dev, le32_to_cpu(txdesc->addr),
+ le32_to_cpu(txdesc->len) >> 16,
+ DMA_TO_DEVICE);
+ dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
+ mdp->tx_skbuff[entry] = NULL;
+ free_num++;
+ }
+ txdesc->status = cpu_to_le32(TD_TFP);
+ if (entry >= mdp->num_tx_ring - 1)
+ txdesc->status |= cpu_to_le32(TD_TDLE);
+
+ if (sent) {
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += le32_to_cpu(txdesc->len) >> 16;
+ }
+ }
+ return free_num;
+}
+
/* free skb and descriptor buffer */
static void sh_eth_ring_free(struct net_device *ndev)
{
struct sh_eth_private *mdp = netdev_priv(ndev);
int ringsize, i;
+ if (mdp->rx_ring) {
+ for (i = 0; i < mdp->num_rx_ring; i++) {
+ if (mdp->rx_skbuff[i]) {
+ struct sh_eth_rxdesc *rxdesc = &mdp->rx_ring[i];
+
+ dma_unmap_single(&ndev->dev,
+ le32_to_cpu(rxdesc->addr),
+ ALIGN(mdp->rx_buf_sz, 32),
+ DMA_FROM_DEVICE);
+ }
+ }
+ ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
+ dma_free_coherent(NULL, ringsize, mdp->rx_ring,
+ mdp->rx_desc_dma);
+ mdp->rx_ring = NULL;
+ }
+
/* Free Rx skb ringbuffer */
if (mdp->rx_skbuff) {
for (i = 0; i < mdp->num_rx_ring; i++)
@@ -1073,27 +1131,18 @@
kfree(mdp->rx_skbuff);
mdp->rx_skbuff = NULL;
- /* Free Tx skb ringbuffer */
- if (mdp->tx_skbuff) {
- for (i = 0; i < mdp->num_tx_ring; i++)
- dev_kfree_skb(mdp->tx_skbuff[i]);
- }
- kfree(mdp->tx_skbuff);
- mdp->tx_skbuff = NULL;
-
- if (mdp->rx_ring) {
- ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
- dma_free_coherent(NULL, ringsize, mdp->rx_ring,
- mdp->rx_desc_dma);
- mdp->rx_ring = NULL;
- }
-
if (mdp->tx_ring) {
+ sh_eth_tx_free(ndev, false);
+
ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
dma_free_coherent(NULL, ringsize, mdp->tx_ring,
mdp->tx_desc_dma);
mdp->tx_ring = NULL;
}
+
+ /* Free Tx skb ringbuffer */
+ kfree(mdp->tx_skbuff);
+ mdp->tx_skbuff = NULL;
}
/* format skb and descriptor buffer */
@@ -1341,43 +1390,6 @@
update_mac_address(ndev);
}
-/* free Tx skb function */
-static int sh_eth_txfree(struct net_device *ndev)
-{
- struct sh_eth_private *mdp = netdev_priv(ndev);
- struct sh_eth_txdesc *txdesc;
- int free_num = 0;
- int entry;
-
- for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
- entry = mdp->dirty_tx % mdp->num_tx_ring;
- txdesc = &mdp->tx_ring[entry];
- if (txdesc->status & cpu_to_le32(TD_TACT))
- break;
- /* TACT bit must be checked before all the following reads */
- dma_rmb();
- netif_info(mdp, tx_done, ndev,
- "tx entry %d status 0x%08x\n",
- entry, le32_to_cpu(txdesc->status));
- /* Free the original skb. */
- if (mdp->tx_skbuff[entry]) {
- dma_unmap_single(&ndev->dev, le32_to_cpu(txdesc->addr),
- le32_to_cpu(txdesc->len) >> 16,
- DMA_TO_DEVICE);
- dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
- mdp->tx_skbuff[entry] = NULL;
- free_num++;
- }
- txdesc->status = cpu_to_le32(TD_TFP);
- if (entry >= mdp->num_tx_ring - 1)
- txdesc->status |= cpu_to_le32(TD_TDLE);
-
- ndev->stats.tx_packets++;
- ndev->stats.tx_bytes += le32_to_cpu(txdesc->len) >> 16;
- }
- return free_num;
-}
-
/* Packet receive function */
static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
{
@@ -1620,7 +1632,7 @@
intr_status, mdp->cur_tx, mdp->dirty_tx,
(u32)ndev->state, edtrr);
/* dirty buffer free */
- sh_eth_txfree(ndev);
+ sh_eth_tx_free(ndev, true);
/* SH7712 BUG */
if (edtrr ^ sh_eth_get_edtrr_trns(mdp)) {
@@ -1679,7 +1691,7 @@
/* Clear Tx interrupts */
sh_eth_write(ndev, intr_status & cd->tx_check, EESR);
- sh_eth_txfree(ndev);
+ sh_eth_tx_free(ndev, true);
netif_wake_queue(ndev);
}
@@ -2307,7 +2319,7 @@
spin_lock_irqsave(&mdp->lock, flags);
if ((mdp->cur_tx - mdp->dirty_tx) >= (mdp->num_tx_ring - 4)) {
- if (!sh_eth_txfree(ndev)) {
+ if (!sh_eth_tx_free(ndev, true)) {
netif_warn(mdp, tx_queued, ndev, "TxFD exhausted.\n");
netif_stop_queue(ndev);
spin_unlock_irqrestore(&mdp->lock, flags);
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index d2e61e0..f7c6a40 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -2709,7 +2709,7 @@
}
#define MACSEC_FEATURES \
- (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST)
+ (NETIF_F_SG | NETIF_F_HIGHDMA)
static struct lock_class_key macsec_netdev_addr_lock_key;
static int macsec_dev_init(struct net_device *dev)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 26d6f0b..dc8ccac 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1140,6 +1140,7 @@
static void macvlan_port_destroy(struct net_device *dev)
{
struct macvlan_port *port = macvlan_port_get_rtnl(dev);
+ struct sk_buff *skb;
dev->priv_flags &= ~IFF_MACVLAN_PORT;
netdev_rx_handler_unregister(dev);
@@ -1148,7 +1149,15 @@
* but we need to cancel it and purge left skbs if any.
*/
cancel_work_sync(&port->bc_work);
- __skb_queue_purge(&port->bc_queue);
+
+ while ((skb = __skb_dequeue(&port->bc_queue))) {
+ const struct macvlan_dev *src = MACVLAN_SKB_CB(skb)->src;
+
+ if (src)
+ dev_put(src->dev);
+
+ kfree_skb(skb);
+ }
kfree_rcu(port, rcu);
}
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 7a240fc..4865221 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -1438,8 +1438,6 @@
skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
skb_queue_tail(&dp83640->rx_queue, skb);
schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT);
- } else {
- netif_rx_ni(skb);
}
return true;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 201ffa5..a9be26f 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -552,16 +552,18 @@
EXPORT_SYMBOL(phy_mii_ioctl);
/**
- * phy_start_aneg - start auto-negotiation for this PHY device
+ * phy_start_aneg_priv - start auto-negotiation for this PHY device
* @phydev: the phy_device struct
+ * @sync: indicate whether we should wait for the workqueue cancelation
*
* Description: Sanitizes the settings (if we're not autonegotiating
* them), and then calls the driver's config_aneg function.
* If the PHYCONTROL Layer is operating, we change the state to
* reflect the beginning of Auto-negotiation or forcing.
*/
-int phy_start_aneg(struct phy_device *phydev)
+static int phy_start_aneg_priv(struct phy_device *phydev, bool sync)
{
+ bool trigger = 0;
int err;
mutex_lock(&phydev->lock);
@@ -586,10 +588,40 @@
}
}
+ /* Re-schedule a PHY state machine to check PHY status because
+ * negotiation may already be done and aneg interrupt may not be
+ * generated.
+ */
+ if (phy_interrupt_is_valid(phydev) && (phydev->state == PHY_AN)) {
+ err = phy_aneg_done(phydev);
+ if (err > 0) {
+ trigger = true;
+ err = 0;
+ }
+ }
+
out_unlock:
mutex_unlock(&phydev->lock);
+
+ if (trigger)
+ phy_trigger_machine(phydev, sync);
+
return err;
}
+
+/**
+ * phy_start_aneg - start auto-negotiation for this PHY device
+ * @phydev: the phy_device struct
+ *
+ * Description: Sanitizes the settings (if we're not autonegotiating
+ * them), and then calls the driver's config_aneg function.
+ * If the PHYCONTROL Layer is operating, we change the state to
+ * reflect the beginning of Auto-negotiation or forcing.
+ */
+int phy_start_aneg(struct phy_device *phydev)
+{
+ return phy_start_aneg_priv(phydev, true);
+}
EXPORT_SYMBOL(phy_start_aneg);
/**
@@ -617,7 +649,7 @@
* state machine runs.
*/
-static void phy_trigger_machine(struct phy_device *phydev, bool sync)
+void phy_trigger_machine(struct phy_device *phydev, bool sync)
{
if (sync)
cancel_delayed_work_sync(&phydev->state_queue);
@@ -639,7 +671,7 @@
cancel_delayed_work_sync(&phydev->state_queue);
mutex_lock(&phydev->lock);
- if (phydev->state > PHY_UP)
+ if (phydev->state > PHY_UP && phydev->state != PHY_HALTED)
phydev->state = PHY_UP;
mutex_unlock(&phydev->lock);
}
@@ -1100,7 +1132,7 @@
mutex_unlock(&phydev->lock);
if (needs_aneg)
- err = phy_start_aneg(phydev);
+ err = phy_start_aneg_priv(phydev, false);
else if (do_suspend)
phy_suspend(phydev);
diff --git a/drivers/net/ppp/pppolac.c b/drivers/net/ppp/pppolac.c
index 0184c96..3a45cf8 100644
--- a/drivers/net/ppp/pppolac.c
+++ b/drivers/net/ppp/pppolac.c
@@ -206,7 +206,9 @@
while ((skb = skb_dequeue(&delivery_queue))) {
struct sock *sk_udp = skb->sk;
struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
- struct msghdr msg = { 0 };
+ struct msghdr msg = {
+ .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
+ };
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1,
skb->len);
diff --git a/drivers/net/ppp/pppopns.c b/drivers/net/ppp/pppopns.c
index d9e0603..cdb4fa1 100644
--- a/drivers/net/ppp/pppopns.c
+++ b/drivers/net/ppp/pppopns.c
@@ -189,7 +189,9 @@
while ((skb = skb_dequeue(&delivery_queue))) {
struct sock *sk_raw = skb->sk;
struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
- struct msghdr msg = { 0 };
+ struct msghdr msg = {
+ .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
+ };
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1,
skb->len);
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index a2afb8e..80ef486 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1124,7 +1124,7 @@
goto nla_put_failure;
/* rule only needs to appear once */
- nlh->nlmsg_flags &= NLM_F_EXCL;
+ nlh->nlmsg_flags |= NLM_F_EXCL;
frh = nlmsg_data(nlh);
memset(frh, 0, sizeof(*frh));
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 6555eb7..6ae8964 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -120,6 +120,20 @@
If unsure, say N.
+config PCI_MSM
+ bool "MSM PCIe Controller driver"
+ depends on ARCH_QCOM && PCI
+ select PCI_DOMAINS
+ select PCI_DOMAINS_GENERIC
+ select PCI_MSI
+ help
+ Enables the PCIe functionality by configuring PCIe core on
+ MSM chipset and by enabling the ARM PCI framework extension.
+ The PCIe core is essential for communication between the host
+ and an endpoint.
+
+ If unsure, say N.
+
config PCI_LABEL
def_bool y if (DMI || ACPI)
select NLS
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 16c9096..a0fa943 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -27,11 +27,11 @@
#include <linux/iommu.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
-#include <linux/regulator/rpm-smd-regulator.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/of_gpio.h>
-#include <linux/clk/msm-clk.h>
+#include <linux/clk/qcom.h>
#include <linux/reset.h>
#include <linux/msm-bus.h>
#include <linux/msm-bus-board.h>
@@ -48,170 +48,27 @@
#include <linux/ipc_logging.h>
#include <linux/msm_pcie.h>
-#ifdef CONFIG_ARCH_MDMCALIFORNIUM
#define PCIE_VENDOR_ID_RCP 0x17cb
-#define PCIE_DEVICE_ID_RCP 0x0302
-
-#define PCIE20_L1SUB_CONTROL1 0x158
-#define PCIE20_PARF_DBI_BASE_ADDR 0x350
-#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x358
-
-#define TX_BASE 0x200
-#define RX_BASE 0x400
-#define PCS_BASE 0x800
-#define PCS_MISC_BASE 0x600
-
-#elif defined(CONFIG_ARCH_MSM8998)
-#define PCIE_VENDOR_ID_RCP 0x17cb
-#define PCIE_DEVICE_ID_RCP 0x0105
+#define PCIE_DEVICE_ID_RCP 0x0106
#define PCIE20_L1SUB_CONTROL1 0x1E4
#define PCIE20_PARF_DBI_BASE_ADDR 0x350
#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x358
-#define TX_BASE 0
-#define RX_BASE 0
#define PCS_BASE 0x800
-#define PCS_MISC_BASE 0
-#else
-#define PCIE_VENDOR_ID_RCP 0x17cb
-#define PCIE_DEVICE_ID_RCP 0x0104
-
-#define PCIE20_L1SUB_CONTROL1 0x158
-#define PCIE20_PARF_DBI_BASE_ADDR 0x168
-#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16C
-
-#define TX_BASE 0x1000
-#define RX_BASE 0x1200
-#define PCS_BASE 0x1400
-#define PCS_MISC_BASE 0
-#endif
-
-#define TX(n, m) (TX_BASE + n * m * 0x1000)
-#define RX(n, m) (RX_BASE + n * m * 0x1000)
#define PCS_PORT(n, m) (PCS_BASE + n * m * 0x1000)
-#define PCS_MISC_PORT(n, m) (PCS_MISC_BASE + n * m * 0x1000)
-
-#define QSERDES_COM_BG_TIMER 0x00C
-#define QSERDES_COM_SSC_EN_CENTER 0x010
-#define QSERDES_COM_SSC_ADJ_PER1 0x014
-#define QSERDES_COM_SSC_ADJ_PER2 0x018
-#define QSERDES_COM_SSC_PER1 0x01C
-#define QSERDES_COM_SSC_PER2 0x020
-#define QSERDES_COM_SSC_STEP_SIZE1 0x024
-#define QSERDES_COM_SSC_STEP_SIZE2 0x028
-#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x034
-#define QSERDES_COM_CLK_ENABLE1 0x038
-#define QSERDES_COM_SYS_CLK_CTRL 0x03C
-#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x040
-#define QSERDES_COM_PLL_IVCO 0x048
-#define QSERDES_COM_LOCK_CMP1_MODE0 0x04C
-#define QSERDES_COM_LOCK_CMP2_MODE0 0x050
-#define QSERDES_COM_LOCK_CMP3_MODE0 0x054
-#define QSERDES_COM_BG_TRIM 0x070
-#define QSERDES_COM_CLK_EP_DIV 0x074
-#define QSERDES_COM_CP_CTRL_MODE0 0x078
-#define QSERDES_COM_PLL_RCTRL_MODE0 0x084
-#define QSERDES_COM_PLL_CCTRL_MODE0 0x090
-#define QSERDES_COM_SYSCLK_EN_SEL 0x0AC
-#define QSERDES_COM_RESETSM_CNTRL 0x0B4
-#define QSERDES_COM_RESTRIM_CTRL 0x0BC
-#define QSERDES_COM_RESCODE_DIV_NUM 0x0C4
-#define QSERDES_COM_LOCK_CMP_EN 0x0C8
-#define QSERDES_COM_DEC_START_MODE0 0x0D0
-#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x0DC
-#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x0E0
-#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x0E4
-#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x108
-#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x10C
-#define QSERDES_COM_VCO_TUNE_CTRL 0x124
-#define QSERDES_COM_VCO_TUNE_MAP 0x128
-#define QSERDES_COM_VCO_TUNE1_MODE0 0x12C
-#define QSERDES_COM_VCO_TUNE2_MODE0 0x130
-#define QSERDES_COM_VCO_TUNE_TIMER1 0x144
-#define QSERDES_COM_VCO_TUNE_TIMER2 0x148
-#define QSERDES_COM_BG_CTRL 0x170
-#define QSERDES_COM_CLK_SELECT 0x174
-#define QSERDES_COM_HSCLK_SEL 0x178
-#define QSERDES_COM_CORECLK_DIV 0x184
-#define QSERDES_COM_CORE_CLK_EN 0x18C
-#define QSERDES_COM_C_READY_STATUS 0x190
-#define QSERDES_COM_CMN_CONFIG 0x194
-#define QSERDES_COM_SVS_MODE_CLK_SEL 0x19C
-#define QSERDES_COM_DEBUG_BUS0 0x1A0
-#define QSERDES_COM_DEBUG_BUS1 0x1A4
-#define QSERDES_COM_DEBUG_BUS2 0x1A8
-#define QSERDES_COM_DEBUG_BUS3 0x1AC
-#define QSERDES_COM_DEBUG_BUS_SEL 0x1B0
-
-#define QSERDES_TX_N_RES_CODE_LANE_OFFSET(n, m) (TX(n, m) + 0x4C)
-#define QSERDES_TX_N_DEBUG_BUS_SEL(n, m) (TX(n, m) + 0x64)
-#define QSERDES_TX_N_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN(n, m) (TX(n, m) + 0x68)
-#define QSERDES_TX_N_LANE_MODE(n, m) (TX(n, m) + 0x94)
-#define QSERDES_TX_N_RCV_DETECT_LVL_2(n, m) (TX(n, m) + 0xAC)
-
-#define QSERDES_RX_N_UCDR_SO_GAIN_HALF(n, m) (RX(n, m) + 0x010)
-#define QSERDES_RX_N_UCDR_SO_GAIN(n, m) (RX(n, m) + 0x01C)
-#define QSERDES_RX_N_UCDR_SO_SATURATION_AND_ENABLE(n, m) (RX(n, m) + 0x048)
-#define QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL2(n, m) (RX(n, m) + 0x0D8)
-#define QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL3(n, m) (RX(n, m) + 0x0DC)
-#define QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL4(n, m) (RX(n, m) + 0x0E0)
-#define QSERDES_RX_N_SIGDET_ENABLES(n, m) (RX(n, m) + 0x110)
-#define QSERDES_RX_N_SIGDET_DEGLITCH_CNTRL(n, m) (RX(n, m) + 0x11C)
-#define QSERDES_RX_N_SIGDET_LVL(n, m) (RX(n, m) + 0x118)
-#define QSERDES_RX_N_RX_BAND(n, m) (RX(n, m) + 0x120)
-
-#define PCIE_MISC_N_DEBUG_BUS_BYTE0_INDEX(n, m) (PCS_MISC_PORT(n, m) + 0x00)
-#define PCIE_MISC_N_DEBUG_BUS_BYTE1_INDEX(n, m) (PCS_MISC_PORT(n, m) + 0x04)
-#define PCIE_MISC_N_DEBUG_BUS_BYTE2_INDEX(n, m) (PCS_MISC_PORT(n, m) + 0x08)
-#define PCIE_MISC_N_DEBUG_BUS_BYTE3_INDEX(n, m) (PCS_MISC_PORT(n, m) + 0x0C)
-#define PCIE_MISC_N_DEBUG_BUS_0_STATUS(n, m) (PCS_MISC_PORT(n, m) + 0x14)
-#define PCIE_MISC_N_DEBUG_BUS_1_STATUS(n, m) (PCS_MISC_PORT(n, m) + 0x18)
-#define PCIE_MISC_N_DEBUG_BUS_2_STATUS(n, m) (PCS_MISC_PORT(n, m) + 0x1C)
-#define PCIE_MISC_N_DEBUG_BUS_3_STATUS(n, m) (PCS_MISC_PORT(n, m) + 0x20)
#define PCIE_N_SW_RESET(n, m) (PCS_PORT(n, m) + 0x00)
#define PCIE_N_POWER_DOWN_CONTROL(n, m) (PCS_PORT(n, m) + 0x04)
-#define PCIE_N_START_CONTROL(n, m) (PCS_PORT(n, m) + 0x08)
-#define PCIE_N_TXDEEMPH_M6DB_V0(n, m) (PCS_PORT(n, m) + 0x24)
-#define PCIE_N_TXDEEMPH_M3P5DB_V0(n, m) (PCS_PORT(n, m) + 0x28)
-#define PCIE_N_ENDPOINT_REFCLK_DRIVE(n, m) (PCS_PORT(n, m) + 0x54)
-#define PCIE_N_RX_IDLE_DTCT_CNTRL(n, m) (PCS_PORT(n, m) + 0x58)
-#define PCIE_N_POWER_STATE_CONFIG1(n, m) (PCS_PORT(n, m) + 0x60)
-#define PCIE_N_POWER_STATE_CONFIG4(n, m) (PCS_PORT(n, m) + 0x6C)
-#define PCIE_N_PWRUP_RESET_DLY_TIME_AUXCLK(n, m) (PCS_PORT(n, m) + 0xA0)
-#define PCIE_N_LP_WAKEUP_DLY_TIME_AUXCLK(n, m) (PCS_PORT(n, m) + 0xA4)
-#define PCIE_N_PLL_LOCK_CHK_DLY_TIME(n, m) (PCS_PORT(n, m) + 0xA8)
-#define PCIE_N_TEST_CONTROL4(n, m) (PCS_PORT(n, m) + 0x11C)
-#define PCIE_N_TEST_CONTROL5(n, m) (PCS_PORT(n, m) + 0x120)
-#define PCIE_N_TEST_CONTROL6(n, m) (PCS_PORT(n, m) + 0x124)
-#define PCIE_N_TEST_CONTROL7(n, m) (PCS_PORT(n, m) + 0x128)
#define PCIE_N_PCS_STATUS(n, m) (PCS_PORT(n, m) + 0x174)
-#define PCIE_N_DEBUG_BUS_0_STATUS(n, m) (PCS_PORT(n, m) + 0x198)
-#define PCIE_N_DEBUG_BUS_1_STATUS(n, m) (PCS_PORT(n, m) + 0x19C)
-#define PCIE_N_DEBUG_BUS_2_STATUS(n, m) (PCS_PORT(n, m) + 0x1A0)
-#define PCIE_N_DEBUG_BUS_3_STATUS(n, m) (PCS_PORT(n, m) + 0x1A4)
-#define PCIE_N_LP_WAKEUP_DLY_TIME_AUXCLK_MSB(n, m) (PCS_PORT(n, m) + 0x1A8)
-#define PCIE_N_OSC_DTCT_ACTIONS(n, m) (PCS_PORT(n, m) + 0x1AC)
-#define PCIE_N_SIGDET_CNTRL(n, m) (PCS_PORT(n, m) + 0x1B0)
-#define PCIE_N_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB(n, m) (PCS_PORT(n, m) + 0x1DC)
-#define PCIE_N_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB(n, m) (PCS_PORT(n, m) + 0x1E0)
#define PCIE_COM_SW_RESET 0x400
#define PCIE_COM_POWER_DOWN_CONTROL 0x404
-#define PCIE_COM_START_CONTROL 0x408
-#define PCIE_COM_DEBUG_BUS_BYTE0_INDEX 0x438
-#define PCIE_COM_DEBUG_BUS_BYTE1_INDEX 0x43C
-#define PCIE_COM_DEBUG_BUS_BYTE2_INDEX 0x440
-#define PCIE_COM_DEBUG_BUS_BYTE3_INDEX 0x444
#define PCIE_COM_PCS_READY_STATUS 0x448
-#define PCIE_COM_DEBUG_BUS_0_STATUS 0x45C
-#define PCIE_COM_DEBUG_BUS_1_STATUS 0x460
-#define PCIE_COM_DEBUG_BUS_2_STATUS 0x464
-#define PCIE_COM_DEBUG_BUS_3_STATUS 0x468
#define PCIE20_PARF_SYS_CTRL 0x00
+#define PCIE20_PARF_PM_CTRL 0x20
#define PCIE20_PARF_PM_STTS 0x24
#define PCIE20_PARF_PCS_DEEMPH 0x34
#define PCIE20_PARF_PCS_SWING 0x38
@@ -228,6 +85,7 @@
#define PCIE20_PARF_SID_OFFSET 0x234
#define PCIE20_PARF_BDF_TRANSLATE_CFG 0x24C
#define PCIE20_PARF_BDF_TRANSLATE_N 0x250
+#define PCIE20_PARF_DEVICE_TYPE 0x1000
#define PCIE20_ELBI_VERSION 0x00
#define PCIE20_ELBI_SYS_CTRL 0x04
@@ -300,7 +158,7 @@
#define MAX_PROP_SIZE 32
#define MAX_RC_NAME_LEN 15
#define MSM_PCIE_MAX_VREG 4
-#define MSM_PCIE_MAX_CLK 9
+#define MSM_PCIE_MAX_CLK 12
#define MSM_PCIE_MAX_PIPE_CLK 1
#define MAX_RC_NUM 3
#define MAX_DEVICE_NUM 20
@@ -314,7 +172,7 @@
#define PCIE_CLEAR 0xDEADBEEF
#define PCIE_LINK_DOWN 0xFFFFFFFF
-#define MSM_PCIE_MAX_RESET 4
+#define MSM_PCIE_MAX_RESET 5
#define MSM_PCIE_MAX_PIPE_RESET 1
#define MSM_PCIE_MSI_PHY 0xa0000000
@@ -629,7 +487,6 @@
uint32_t wr_halt_size;
uint32_t cpl_timeout;
uint32_t current_bdf;
- short current_short_bdf;
uint32_t perst_delay_us_min;
uint32_t perst_delay_us_max;
uint32_t tlp_rd_size;
@@ -734,18 +591,21 @@
static struct msm_pcie_reset_info_t
msm_pcie_reset_info[MAX_RC_NUM][MSM_PCIE_MAX_RESET] = {
{
+ {NULL, "pcie_0_core_reset", false},
{NULL, "pcie_phy_reset", false},
{NULL, "pcie_phy_com_reset", false},
{NULL, "pcie_phy_nocsr_com_phy_reset", false},
{NULL, "pcie_0_phy_reset", false}
},
{
+ {NULL, "pcie_1_core_reset", false},
{NULL, "pcie_phy_reset", false},
{NULL, "pcie_phy_com_reset", false},
{NULL, "pcie_phy_nocsr_com_phy_reset", false},
{NULL, "pcie_1_phy_reset", false}
},
{
+ {NULL, "pcie_2_core_reset", false},
{NULL, "pcie_phy_reset", false},
{NULL, "pcie_phy_com_reset", false},
{NULL, "pcie_phy_nocsr_com_phy_reset", false},
@@ -778,6 +638,9 @@
{NULL, "pcie_0_slv_axi_clk", 0, true, true},
{NULL, "pcie_0_ldo", 0, false, true},
{NULL, "pcie_0_smmu_clk", 0, false, false},
+ {NULL, "pcie_0_slv_q2a_axi_clk", 0, false, false},
+ {NULL, "pcie_phy_refgen_clk", 0, false, false},
+ {NULL, "pcie_tbu_clk", 0, false, false},
{NULL, "pcie_phy_cfg_ahb_clk", 0, false, false},
{NULL, "pcie_phy_aux_clk", 0, false, false}
},
@@ -789,6 +652,9 @@
{NULL, "pcie_1_slv_axi_clk", 0, true, true},
{NULL, "pcie_1_ldo", 0, false, true},
{NULL, "pcie_1_smmu_clk", 0, false, false},
+ {NULL, "pcie_1_slv_q2a_axi_clk", 0, false, false},
+ {NULL, "pcie_phy_refgen_clk", 0, false, false},
+ {NULL, "pcie_tbu_clk", 0, false, false},
{NULL, "pcie_phy_cfg_ahb_clk", 0, false, false},
{NULL, "pcie_phy_aux_clk", 0, false, false}
},
@@ -800,6 +666,9 @@
{NULL, "pcie_2_slv_axi_clk", 0, true, true},
{NULL, "pcie_2_ldo", 0, false, true},
{NULL, "pcie_2_smmu_clk", 0, false, false},
+ {NULL, "pcie_2_slv_q2a_axi_clk", 0, false, false},
+ {NULL, "pcie_phy_refgen_clk", 0, false, false},
+ {NULL, "pcie_tbu_clk", 0, false, false},
{NULL, "pcie_phy_cfg_ahb_clk", 0, false, false},
{NULL, "pcie_phy_aux_clk", 0, false, false}
}
@@ -860,6 +729,8 @@
{"msi_28", 0}, {"msi_29", 0}, {"msi_30", 0}, {"msi_31", 0}
};
+static int msm_pcie_config_device(struct pci_dev *dev, void *pdev);
+
#ifdef CONFIG_ARM
#define PCIE_BUS_PRIV_DATA(bus) \
(((struct pci_sys_data *)bus->sysdata)->private_data)
@@ -938,393 +809,9 @@
dev->rc_idx, info->name);
}
-#if defined(CONFIG_ARCH_FSM9010)
-#define PCIE20_PARF_PHY_STTS 0x3c
-#define PCIE2_PHY_RESET_CTRL 0x44
-#define PCIE20_PARF_PHY_REFCLK_CTRL2 0xa0
-#define PCIE20_PARF_PHY_REFCLK_CTRL3 0xa4
-#define PCIE20_PARF_PCS_SWING_CTRL1 0x88
-#define PCIE20_PARF_PCS_SWING_CTRL2 0x8c
-#define PCIE20_PARF_PCS_DEEMPH1 0x74
-#define PCIE20_PARF_PCS_DEEMPH2 0x78
-#define PCIE20_PARF_PCS_DEEMPH3 0x7c
-#define PCIE20_PARF_CONFIGBITS 0x84
-#define PCIE20_PARF_PHY_CTRL3 0x94
-#define PCIE20_PARF_PCS_CTRL 0x80
-
-#define TX_AMP_VAL 127
-#define PHY_RX0_EQ_GEN1_VAL 0
-#define PHY_RX0_EQ_GEN2_VAL 4
-#define TX_DEEMPH_GEN1_VAL 24
-#define TX_DEEMPH_GEN2_3_5DB_VAL 24
-#define TX_DEEMPH_GEN2_6DB_VAL 34
-#define PHY_TX0_TERM_OFFST_VAL 0
-
-static inline void pcie_phy_dump(struct msm_pcie_dev_t *dev)
-{
-}
-
-static inline void pcie20_phy_reset(struct msm_pcie_dev_t *dev, uint32_t assert)
-{
- msm_pcie_write_reg_field(dev->phy, PCIE2_PHY_RESET_CTRL,
- BIT(0), (assert) ? 1 : 0);
-}
-
-static void pcie_phy_init(struct msm_pcie_dev_t *dev)
-{
- PCIE_DBG(dev, "RC%d: Initializing 28LP SNS phy - 100MHz\n",
- dev->rc_idx);
-
- /* De-assert Phy SW Reset */
- pcie20_phy_reset(dev, 1);
-
- /* Program SSP ENABLE */
- if (readl_relaxed(dev->phy + PCIE20_PARF_PHY_REFCLK_CTRL2) & BIT(0))
- msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PHY_REFCLK_CTRL2,
- BIT(0), 0);
- if ((readl_relaxed(dev->phy + PCIE20_PARF_PHY_REFCLK_CTRL3) &
- BIT(0)) == 0)
- msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PHY_REFCLK_CTRL3,
- BIT(0), 1);
- /* Program Tx Amplitude */
- if ((readl_relaxed(dev->phy + PCIE20_PARF_PCS_SWING_CTRL1) &
- (BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
- TX_AMP_VAL)
- msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_SWING_CTRL1,
- BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
- TX_AMP_VAL);
- if ((readl_relaxed(dev->phy + PCIE20_PARF_PCS_SWING_CTRL2) &
- (BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
- TX_AMP_VAL)
- msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_SWING_CTRL2,
- BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
- TX_AMP_VAL);
- /* Program De-Emphasis */
- if ((readl_relaxed(dev->phy + PCIE20_PARF_PCS_DEEMPH1) &
- (BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
- TX_DEEMPH_GEN2_6DB_VAL)
- msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_DEEMPH1,
- BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
- TX_DEEMPH_GEN2_6DB_VAL);
-
- if ((readl_relaxed(dev->phy + PCIE20_PARF_PCS_DEEMPH2) &
- (BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
- TX_DEEMPH_GEN2_3_5DB_VAL)
- msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_DEEMPH2,
- BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
- TX_DEEMPH_GEN2_3_5DB_VAL);
-
- if ((readl_relaxed(dev->phy + PCIE20_PARF_PCS_DEEMPH3) &
- (BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
- TX_DEEMPH_GEN1_VAL)
- msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_DEEMPH3,
- BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
- TX_DEEMPH_GEN1_VAL);
-
- /* Program Rx_Eq */
- if ((readl_relaxed(dev->phy + PCIE20_PARF_CONFIGBITS) &
- (BIT(2)|BIT(1)|BIT(0))) != PHY_RX0_EQ_GEN1_VAL)
- msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_CONFIGBITS,
- BIT(2)|BIT(1)|BIT(0), PHY_RX0_EQ_GEN1_VAL);
-
- /* Program Tx0_term_offset */
- if ((readl_relaxed(dev->phy + PCIE20_PARF_PHY_CTRL3) &
- (BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
- PHY_TX0_TERM_OFFST_VAL)
- msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PHY_CTRL3,
- BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
- PHY_TX0_TERM_OFFST_VAL);
-
- /* Program REF_CLK source */
- msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PHY_REFCLK_CTRL2, BIT(1),
- (dev->ext_ref_clk) ? 1 : 0);
- /* disable Tx2Rx Loopback */
- if (readl_relaxed(dev->phy + PCIE20_PARF_PCS_CTRL) & BIT(1))
- msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_CTRL,
- BIT(1), 0);
- /* De-assert Phy SW Reset */
- pcie20_phy_reset(dev, 0);
-}
-
-static bool pcie_phy_is_ready(struct msm_pcie_dev_t *dev)
-{
-
- /* read PCIE20_PARF_PHY_STTS twice */
- readl_relaxed(dev->phy + PCIE20_PARF_PHY_STTS);
- if (readl_relaxed(dev->phy + PCIE20_PARF_PHY_STTS) & BIT(0))
- return false;
- else
- return true;
-}
-#else
-static void pcie_phy_dump_test_cntrl(struct msm_pcie_dev_t *dev,
- u32 cntrl4_val, u32 cntrl5_val,
- u32 cntrl6_val, u32 cntrl7_val)
-{
- msm_pcie_write_reg(dev->phy,
- PCIE_N_TEST_CONTROL4(dev->rc_idx, dev->common_phy), cntrl4_val);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_TEST_CONTROL5(dev->rc_idx, dev->common_phy), cntrl5_val);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_TEST_CONTROL6(dev->rc_idx, dev->common_phy), cntrl6_val);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_TEST_CONTROL7(dev->rc_idx, dev->common_phy), cntrl7_val);
-
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_N_TEST_CONTROL4: 0x%x\n", dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_N_TEST_CONTROL4(dev->rc_idx,
- dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_N_TEST_CONTROL5: 0x%x\n", dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_N_TEST_CONTROL5(dev->rc_idx,
- dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_N_TEST_CONTROL6: 0x%x\n", dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_N_TEST_CONTROL6(dev->rc_idx,
- dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_N_TEST_CONTROL7: 0x%x\n", dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_N_TEST_CONTROL7(dev->rc_idx,
- dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_N_DEBUG_BUS_0_STATUS: 0x%x\n", dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_N_DEBUG_BUS_0_STATUS(dev->rc_idx,
- dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_N_DEBUG_BUS_1_STATUS: 0x%x\n", dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_N_DEBUG_BUS_1_STATUS(dev->rc_idx,
- dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_N_DEBUG_BUS_2_STATUS: 0x%x\n", dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_N_DEBUG_BUS_2_STATUS(dev->rc_idx,
- dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_N_DEBUG_BUS_3_STATUS: 0x%x\n\n", dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_N_DEBUG_BUS_3_STATUS(dev->rc_idx,
- dev->common_phy)));
-}
-
static void pcie_phy_dump(struct msm_pcie_dev_t *dev)
{
int i, size;
- u32 write_val;
-
- if (dev->phy_ver >= 0x20) {
- PCIE_DUMP(dev, "PCIe: RC%d PHY dump is not supported\n",
- dev->rc_idx);
- return;
- }
-
- PCIE_DUMP(dev, "PCIe: RC%d PHY testbus\n", dev->rc_idx);
-
- pcie_phy_dump_test_cntrl(dev, 0x18, 0x19, 0x1A, 0x1B);
- pcie_phy_dump_test_cntrl(dev, 0x1C, 0x1D, 0x1E, 0x1F);
- pcie_phy_dump_test_cntrl(dev, 0x20, 0x21, 0x22, 0x23);
-
- for (i = 0; i < 3; i++) {
- write_val = 0x1 + i;
- msm_pcie_write_reg(dev->phy,
- QSERDES_TX_N_DEBUG_BUS_SEL(dev->rc_idx,
- dev->common_phy), write_val);
- PCIE_DUMP(dev,
- "PCIe: RC%d QSERDES_TX_N_DEBUG_BUS_SEL: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- QSERDES_TX_N_DEBUG_BUS_SEL(dev->rc_idx,
- dev->common_phy)));
-
- pcie_phy_dump_test_cntrl(dev, 0x30, 0x31, 0x32, 0x33);
- }
-
- pcie_phy_dump_test_cntrl(dev, 0, 0, 0, 0);
-
- if (dev->phy_ver >= 0x10 && dev->phy_ver < 0x20) {
- pcie_phy_dump_test_cntrl(dev, 0x01, 0x02, 0x03, 0x0A);
- pcie_phy_dump_test_cntrl(dev, 0x0E, 0x0F, 0x12, 0x13);
- pcie_phy_dump_test_cntrl(dev, 0, 0, 0, 0);
-
- for (i = 0; i < 8; i += 4) {
- write_val = 0x1 + i;
- msm_pcie_write_reg(dev->phy,
- PCIE_MISC_N_DEBUG_BUS_BYTE0_INDEX(dev->rc_idx,
- dev->common_phy), write_val);
- msm_pcie_write_reg(dev->phy,
- PCIE_MISC_N_DEBUG_BUS_BYTE1_INDEX(dev->rc_idx,
- dev->common_phy), write_val + 1);
- msm_pcie_write_reg(dev->phy,
- PCIE_MISC_N_DEBUG_BUS_BYTE2_INDEX(dev->rc_idx,
- dev->common_phy), write_val + 2);
- msm_pcie_write_reg(dev->phy,
- PCIE_MISC_N_DEBUG_BUS_BYTE3_INDEX(dev->rc_idx,
- dev->common_phy), write_val + 3);
-
- PCIE_DUMP(dev,
- "PCIe: RC%d to PCIE_MISC_N_DEBUG_BUS_BYTE0_INDEX: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_MISC_N_DEBUG_BUS_BYTE0_INDEX(
- dev->rc_idx, dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d to PCIE_MISC_N_DEBUG_BUS_BYTE1_INDEX: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_MISC_N_DEBUG_BUS_BYTE1_INDEX(
- dev->rc_idx, dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d to PCIE_MISC_N_DEBUG_BUS_BYTE2_INDEX: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_MISC_N_DEBUG_BUS_BYTE2_INDEX(
- dev->rc_idx, dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d to PCIE_MISC_N_DEBUG_BUS_BYTE3_INDEX: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_MISC_N_DEBUG_BUS_BYTE3_INDEX(
- dev->rc_idx, dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_MISC_N_DEBUG_BUS_0_STATUS: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_MISC_N_DEBUG_BUS_0_STATUS(
- dev->rc_idx, dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_MISC_N_DEBUG_BUS_1_STATUS: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_MISC_N_DEBUG_BUS_1_STATUS(
- dev->rc_idx, dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_MISC_N_DEBUG_BUS_2_STATUS: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_MISC_N_DEBUG_BUS_2_STATUS(
- dev->rc_idx, dev->common_phy)));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_MISC_N_DEBUG_BUS_3_STATUS: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_MISC_N_DEBUG_BUS_3_STATUS(
- dev->rc_idx, dev->common_phy)));
- }
-
- msm_pcie_write_reg(dev->phy,
- PCIE_MISC_N_DEBUG_BUS_BYTE0_INDEX(
- dev->rc_idx, dev->common_phy), 0);
- msm_pcie_write_reg(dev->phy,
- PCIE_MISC_N_DEBUG_BUS_BYTE1_INDEX(
- dev->rc_idx, dev->common_phy), 0);
- msm_pcie_write_reg(dev->phy,
- PCIE_MISC_N_DEBUG_BUS_BYTE2_INDEX(
- dev->rc_idx, dev->common_phy), 0);
- msm_pcie_write_reg(dev->phy,
- PCIE_MISC_N_DEBUG_BUS_BYTE3_INDEX(
- dev->rc_idx, dev->common_phy), 0);
- }
-
- for (i = 0; i < 2; i++) {
- write_val = 0x2 + i;
-
- msm_pcie_write_reg(dev->phy, QSERDES_COM_DEBUG_BUS_SEL,
- write_val);
-
- PCIE_DUMP(dev,
- "PCIe: RC%d to QSERDES_COM_DEBUG_BUS_SEL: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy + QSERDES_COM_DEBUG_BUS_SEL));
- PCIE_DUMP(dev,
- "PCIe: RC%d QSERDES_COM_DEBUG_BUS0: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy + QSERDES_COM_DEBUG_BUS0));
- PCIE_DUMP(dev,
- "PCIe: RC%d QSERDES_COM_DEBUG_BUS1: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy + QSERDES_COM_DEBUG_BUS1));
- PCIE_DUMP(dev,
- "PCIe: RC%d QSERDES_COM_DEBUG_BUS2: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy + QSERDES_COM_DEBUG_BUS2));
- PCIE_DUMP(dev,
- "PCIe: RC%d QSERDES_COM_DEBUG_BUS3: 0x%x\n\n",
- dev->rc_idx,
- readl_relaxed(dev->phy + QSERDES_COM_DEBUG_BUS3));
- }
-
- msm_pcie_write_reg(dev->phy, QSERDES_COM_DEBUG_BUS_SEL, 0);
-
- if (dev->common_phy) {
- msm_pcie_write_reg(dev->phy, PCIE_COM_DEBUG_BUS_BYTE0_INDEX,
- 0x01);
- msm_pcie_write_reg(dev->phy, PCIE_COM_DEBUG_BUS_BYTE1_INDEX,
- 0x02);
- msm_pcie_write_reg(dev->phy, PCIE_COM_DEBUG_BUS_BYTE2_INDEX,
- 0x03);
- msm_pcie_write_reg(dev->phy, PCIE_COM_DEBUG_BUS_BYTE3_INDEX,
- 0x04);
-
- PCIE_DUMP(dev,
- "PCIe: RC%d to PCIE_COM_DEBUG_BUS_BYTE0_INDEX: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_COM_DEBUG_BUS_BYTE0_INDEX));
- PCIE_DUMP(dev,
- "PCIe: RC%d to PCIE_COM_DEBUG_BUS_BYTE1_INDEX: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_COM_DEBUG_BUS_BYTE1_INDEX));
- PCIE_DUMP(dev,
- "PCIe: RC%d to PCIE_COM_DEBUG_BUS_BYTE2_INDEX: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_COM_DEBUG_BUS_BYTE2_INDEX));
- PCIE_DUMP(dev,
- "PCIe: RC%d to PCIE_COM_DEBUG_BUS_BYTE3_INDEX: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_COM_DEBUG_BUS_BYTE3_INDEX));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_COM_DEBUG_BUS_0_STATUS: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_COM_DEBUG_BUS_0_STATUS));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_COM_DEBUG_BUS_1_STATUS: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_COM_DEBUG_BUS_1_STATUS));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_COM_DEBUG_BUS_2_STATUS: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_COM_DEBUG_BUS_2_STATUS));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_COM_DEBUG_BUS_3_STATUS: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_COM_DEBUG_BUS_3_STATUS));
-
- msm_pcie_write_reg(dev->phy, PCIE_COM_DEBUG_BUS_BYTE0_INDEX,
- 0x05);
-
- PCIE_DUMP(dev,
- "PCIe: RC%d to PCIE_COM_DEBUG_BUS_BYTE0_INDEX: 0x%x\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_COM_DEBUG_BUS_BYTE0_INDEX));
- PCIE_DUMP(dev,
- "PCIe: RC%d PCIE_COM_DEBUG_BUS_0_STATUS: 0x%x\n\n",
- dev->rc_idx,
- readl_relaxed(dev->phy +
- PCIE_COM_DEBUG_BUS_0_STATUS));
- }
size = resource_size(dev->res[MSM_PCIE_RES_PHY].resource);
for (i = 0; i < size; i += 32) {
@@ -1342,181 +829,6 @@
}
}
-#ifdef CONFIG_ARCH_MDMCALIFORNIUM
-static void pcie_phy_init(struct msm_pcie_dev_t *dev)
-{
- u8 common_phy;
-
- PCIE_DBG(dev,
- "RC%d: Initializing MDM 14nm QMP phy - 19.2MHz with Common Mode Clock (SSC ON)\n",
- dev->rc_idx);
-
- if (dev->common_phy)
- common_phy = 1;
- else
- common_phy = 0;
-
- msm_pcie_write_reg(dev->phy,
- PCIE_N_SW_RESET(dev->rc_idx, common_phy),
- 0x01);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_POWER_DOWN_CONTROL(dev->rc_idx, common_phy),
- 0x03);
-
- msm_pcie_write_reg(dev->phy, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_ENABLE1, 0x10);
-
- msm_pcie_write_reg(dev->phy,
- QSERDES_TX_N_LANE_MODE(dev->rc_idx, common_phy), 0x06);
-
- msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP_EN, 0x01);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_MAP, 0x00);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_TIMER1, 0xFF);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_TIMER2, 0x1F);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_BG_TRIM, 0x0F);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_IVCO, 0x0F);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_HSCLK_SEL, 0x00);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SVS_MODE_CLK_SEL, 0x01);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CORE_CLK_EN, 0x20);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CORECLK_DIV, 0x0A);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_BG_TIMER, 0x09);
-
- if (dev->tcsr) {
- PCIE_DBG(dev, "RC%d: TCSR PHY clock scheme is 0x%x\n",
- dev->rc_idx, readl_relaxed(dev->tcsr));
-
- if (readl_relaxed(dev->tcsr) & (BIT(1) | BIT(0)))
- msm_pcie_write_reg(dev->phy,
- QSERDES_COM_SYSCLK_EN_SEL, 0x0A);
- else
- msm_pcie_write_reg(dev->phy,
- QSERDES_COM_SYSCLK_EN_SEL, 0x04);
- }
-
- msm_pcie_write_reg(dev->phy, QSERDES_COM_DEC_START_MODE0, 0x82);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP3_MODE0, 0x00);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP2_MODE0, 0x0D);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP1_MODE0, 0x04);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_SELECT, 0x33);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SYS_CLK_CTRL, 0x02);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1F);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CP_CTRL_MODE0, 0x0B);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_CCTRL_MODE0, 0x28);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80);
-
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_EN_CENTER, 0x01);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_PER1, 0x31);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_PER2, 0x01);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_ADJ_PER1, 0x02);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_ADJ_PER2, 0x00);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_STEP_SIZE1, 0x2f);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_STEP_SIZE2, 0x19);
-
- msm_pcie_write_reg(dev->phy,
- QSERDES_TX_N_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN(dev->rc_idx,
- common_phy), 0x45);
-
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CMN_CONFIG, 0x06);
-
- msm_pcie_write_reg(dev->phy,
- QSERDES_TX_N_RES_CODE_LANE_OFFSET(dev->rc_idx, common_phy),
- 0x02);
- msm_pcie_write_reg(dev->phy,
- QSERDES_TX_N_RCV_DETECT_LVL_2(dev->rc_idx, common_phy),
- 0x12);
-
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_SIGDET_ENABLES(dev->rc_idx, common_phy),
- 0x1C);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_SIGDET_DEGLITCH_CNTRL(dev->rc_idx, common_phy),
- 0x14);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL2(dev->rc_idx, common_phy),
- 0x01);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL3(dev->rc_idx, common_phy),
- 0x00);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL4(dev->rc_idx, common_phy),
- 0xDB);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_UCDR_SO_SATURATION_AND_ENABLE(dev->rc_idx,
- common_phy),
- 0x4B);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_UCDR_SO_GAIN(dev->rc_idx, common_phy),
- 0x04);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_UCDR_SO_GAIN_HALF(dev->rc_idx, common_phy),
- 0x04);
-
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_EP_DIV, 0x19);
-
- msm_pcie_write_reg(dev->phy,
- PCIE_N_ENDPOINT_REFCLK_DRIVE(dev->rc_idx, common_phy),
- 0x04);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_OSC_DTCT_ACTIONS(dev->rc_idx, common_phy),
- 0x00);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_PWRUP_RESET_DLY_TIME_AUXCLK(dev->rc_idx, common_phy),
- 0x40);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB(dev->rc_idx, common_phy),
- 0x00);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB(dev->rc_idx, common_phy),
- 0x40);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_LP_WAKEUP_DLY_TIME_AUXCLK_MSB(dev->rc_idx, common_phy),
- 0x00);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_LP_WAKEUP_DLY_TIME_AUXCLK(dev->rc_idx, common_phy),
- 0x40);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_PLL_LOCK_CHK_DLY_TIME(dev->rc_idx, common_phy),
- 0x73);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_SIGDET_LVL(dev->rc_idx, common_phy),
- 0x99);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_TXDEEMPH_M6DB_V0(dev->rc_idx, common_phy),
- 0x15);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_TXDEEMPH_M3P5DB_V0(dev->rc_idx, common_phy),
- 0x0E);
-
- msm_pcie_write_reg(dev->phy,
- PCIE_N_SIGDET_CNTRL(dev->rc_idx, common_phy),
- 0x07);
-
- msm_pcie_write_reg(dev->phy,
- PCIE_N_SW_RESET(dev->rc_idx, common_phy),
- 0x00);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_START_CONTROL(dev->rc_idx, common_phy),
- 0x03);
-}
-
-static void pcie_pcs_port_phy_init(struct msm_pcie_dev_t *dev)
-{
-}
-
-static bool pcie_phy_is_ready(struct msm_pcie_dev_t *dev)
-{
- if (readl_relaxed(dev->phy +
- PCIE_N_PCS_STATUS(dev->rc_idx, dev->common_phy)) & BIT(6))
- return false;
- else
- return true;
-}
-#else
static void pcie_phy_init(struct msm_pcie_dev_t *dev)
{
int i;
@@ -1538,64 +850,6 @@
phy_seq->delay + 1);
phy_seq++;
}
- return;
- }
-
- if (dev->common_phy)
- msm_pcie_write_reg(dev->phy, PCIE_COM_POWER_DOWN_CONTROL, 0x01);
-
- msm_pcie_write_reg(dev->phy, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1C);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_ENABLE1, 0x10);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_SELECT, 0x33);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CMN_CONFIG, 0x06);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP_EN, 0x42);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_MAP, 0x00);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_TIMER1, 0xFF);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_TIMER2, 0x1F);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_HSCLK_SEL, 0x01);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SVS_MODE_CLK_SEL, 0x01);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CORE_CLK_EN, 0x00);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CORECLK_DIV, 0x0A);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_BG_TIMER, 0x09);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_DEC_START_MODE0, 0x82);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP3_MODE0, 0x00);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP2_MODE0, 0x1A);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP1_MODE0, 0x0A);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_SELECT, 0x33);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SYS_CLK_CTRL, 0x02);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1F);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SYSCLK_EN_SEL, 0x04);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CP_CTRL_MODE0, 0x0B);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_CCTRL_MODE0, 0x28);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_EN_CENTER, 0x01);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_PER1, 0x31);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_PER2, 0x01);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_ADJ_PER1, 0x02);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_ADJ_PER2, 0x00);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_STEP_SIZE1, 0x2f);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_STEP_SIZE2, 0x19);
-
- msm_pcie_write_reg(dev->phy, QSERDES_COM_RESCODE_DIV_NUM, 0x15);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_BG_TRIM, 0x0F);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_IVCO, 0x0F);
-
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_EP_DIV, 0x19);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_ENABLE1, 0x10);
-
- if (dev->phy_ver == 0x3) {
- msm_pcie_write_reg(dev->phy, QSERDES_COM_HSCLK_SEL, 0x00);
- msm_pcie_write_reg(dev->phy, QSERDES_COM_RESCODE_DIV_NUM, 0x40);
- }
-
- if (dev->common_phy) {
- msm_pcie_write_reg(dev->phy, PCIE_COM_SW_RESET, 0x00);
- msm_pcie_write_reg(dev->phy, PCIE_COM_START_CONTROL, 0x03);
}
}
@@ -1603,18 +857,9 @@
{
int i;
struct msm_pcie_phy_info_t *phy_seq;
- u8 common_phy;
-
- if (dev->phy_ver >= 0x20)
- return;
PCIE_DBG(dev, "RC%d: Initializing PCIe PHY Port\n", dev->rc_idx);
- if (dev->common_phy)
- common_phy = 1;
- else
- common_phy = 0;
-
if (dev->port_phy_sequence) {
i = dev->port_phy_len;
phy_seq = dev->port_phy_sequence;
@@ -1627,93 +872,8 @@
phy_seq->delay + 1);
phy_seq++;
}
- return;
}
- msm_pcie_write_reg(dev->phy,
- QSERDES_TX_N_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN(dev->rc_idx,
- common_phy), 0x45);
- msm_pcie_write_reg(dev->phy,
- QSERDES_TX_N_LANE_MODE(dev->rc_idx, common_phy),
- 0x06);
-
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_SIGDET_ENABLES(dev->rc_idx, common_phy),
- 0x1C);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_SIGDET_LVL(dev->rc_idx, common_phy),
- 0x17);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL2(dev->rc_idx, common_phy),
- 0x01);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL3(dev->rc_idx, common_phy),
- 0x00);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL4(dev->rc_idx, common_phy),
- 0xDB);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_RX_BAND(dev->rc_idx, common_phy),
- 0x18);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_UCDR_SO_GAIN(dev->rc_idx, common_phy),
- 0x04);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_UCDR_SO_GAIN_HALF(dev->rc_idx, common_phy),
- 0x04);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_RX_IDLE_DTCT_CNTRL(dev->rc_idx, common_phy),
- 0x4C);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_PWRUP_RESET_DLY_TIME_AUXCLK(dev->rc_idx, common_phy),
- 0x00);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_LP_WAKEUP_DLY_TIME_AUXCLK(dev->rc_idx, common_phy),
- 0x01);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_PLL_LOCK_CHK_DLY_TIME(dev->rc_idx, common_phy),
- 0x05);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_UCDR_SO_SATURATION_AND_ENABLE(dev->rc_idx,
- common_phy), 0x4B);
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_SIGDET_DEGLITCH_CNTRL(dev->rc_idx, common_phy),
- 0x14);
-
- msm_pcie_write_reg(dev->phy,
- PCIE_N_ENDPOINT_REFCLK_DRIVE(dev->rc_idx, common_phy),
- 0x05);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_POWER_DOWN_CONTROL(dev->rc_idx, common_phy),
- 0x02);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_POWER_STATE_CONFIG4(dev->rc_idx, common_phy),
- 0x00);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_POWER_STATE_CONFIG1(dev->rc_idx, common_phy),
- 0xA3);
-
- if (dev->phy_ver == 0x3) {
- msm_pcie_write_reg(dev->phy,
- QSERDES_RX_N_SIGDET_LVL(dev->rc_idx, common_phy),
- 0x19);
-
- msm_pcie_write_reg(dev->phy,
- PCIE_N_TXDEEMPH_M3P5DB_V0(dev->rc_idx, common_phy),
- 0x0E);
- }
-
- msm_pcie_write_reg(dev->phy,
- PCIE_N_POWER_DOWN_CONTROL(dev->rc_idx, common_phy),
- 0x03);
- usleep_range(POWER_DOWN_DELAY_US_MIN, POWER_DOWN_DELAY_US_MAX);
-
- msm_pcie_write_reg(dev->phy,
- PCIE_N_SW_RESET(dev->rc_idx, common_phy),
- 0x00);
- msm_pcie_write_reg(dev->phy,
- PCIE_N_START_CONTROL(dev->rc_idx, common_phy),
- 0x0A);
}
static bool pcie_phy_is_ready(struct msm_pcie_dev_t *dev)
@@ -1732,8 +892,6 @@
else
return true;
}
-#endif
-#endif
static int msm_pcie_restore_sec_config(struct msm_pcie_dev_t *dev)
{
@@ -1975,8 +1133,6 @@
dev->msi_gicm_base);
PCIE_DBG_FS(dev, "bus_client: %d\n",
dev->bus_client);
- PCIE_DBG_FS(dev, "current short bdf: %d\n",
- dev->current_short_bdf);
PCIE_DBG_FS(dev, "smmu does %s exist\n",
dev->smmu_exist ? "" : "not");
PCIE_DBG_FS(dev, "smmu_sid_base: 0x%x\n",
@@ -3512,8 +2668,8 @@
dev->rc_idx,
dev->vreg[i].name);
regulator_set_voltage(hdl,
- RPM_REGULATOR_CORNER_NONE,
- INT_MAX);
+ RPMH_REGULATOR_LEVEL_OFF,
+ RPMH_REGULATOR_LEVEL_MAX);
}
}
@@ -3542,8 +2698,8 @@
dev->rc_idx,
dev->vreg[i].name);
regulator_set_voltage(dev->vreg[i].hdl,
- RPM_REGULATOR_CORNER_NONE,
- INT_MAX);
+ RPMH_REGULATOR_LEVEL_OFF,
+ RPMH_REGULATOR_LEVEL_MAX);
}
}
}
@@ -3645,6 +2801,19 @@
for (i = 0; i < MSM_PCIE_MAX_RESET; i++) {
reset_info = &dev->reset[i];
if (reset_info->hdl) {
+ rc = reset_control_assert(reset_info->hdl);
+ if (rc)
+ PCIE_ERR(dev,
+ "PCIe: RC%d failed to assert reset for %s.\n",
+ dev->rc_idx, reset_info->name);
+ else
+ PCIE_DBG2(dev,
+ "PCIe: RC%d successfully asserted reset for %s.\n",
+ dev->rc_idx, reset_info->name);
+
+ /* add a 1ms delay to ensure the reset is asserted */
+ usleep_range(1000, 1005);
+
rc = reset_control_deassert(reset_info->hdl);
if (rc)
PCIE_ERR(dev,
@@ -3749,6 +2918,19 @@
for (i = 0; i < MSM_PCIE_MAX_PIPE_RESET; i++) {
pipe_reset_info = &dev->pipe_reset[i];
if (pipe_reset_info->hdl) {
+ rc = reset_control_assert(pipe_reset_info->hdl);
+ if (rc)
+ PCIE_ERR(dev,
+ "PCIe: RC%d failed to assert pipe reset for %s.\n",
+ dev->rc_idx, pipe_reset_info->name);
+ else
+ PCIE_DBG2(dev,
+ "PCIe: RC%d successfully asserted pipe reset for %s.\n",
+ dev->rc_idx, pipe_reset_info->name);
+
+ /* add a 1ms delay to ensure the reset is asserted */
+ usleep_range(1000, 1005);
+
rc = reset_control_deassert(
pipe_reset_info->hdl);
if (rc)
@@ -3802,8 +2984,6 @@
static void msm_pcie_config_controller(struct msm_pcie_dev_t *dev)
{
- int i;
-
PCIE_DBG(dev, "RC%d\n", dev->rc_idx);
/*
@@ -3859,27 +3039,6 @@
PCIE_DBG(dev, "RC's PCIE20_CAP_DEVCTRLSTATUS:0x%x\n",
readl_relaxed(dev->dm_core + PCIE20_CAP_DEVCTRLSTATUS));
}
-
- /* configure SMMU registers */
- if (dev->smmu_exist) {
- msm_pcie_write_reg(dev->parf,
- PCIE20_PARF_BDF_TRANSLATE_CFG, 0);
- msm_pcie_write_reg(dev->parf,
- PCIE20_PARF_SID_OFFSET, 0);
-
- if (dev->enumerated) {
- for (i = 0; i < MAX_DEVICE_NUM; i++) {
- if (dev->pcidev_table[i].dev &&
- dev->pcidev_table[i].short_bdf) {
- msm_pcie_write_reg(dev->parf,
- PCIE20_PARF_BDF_TRANSLATE_N +
- dev->pcidev_table[i].short_bdf
- * 4,
- dev->pcidev_table[i].bdf >> 16);
- }
- }
- }
- }
}
static void msm_pcie_config_link_state(struct msm_pcie_dev_t *dev)
@@ -4527,6 +3686,13 @@
msm_pcie_restore_sec_config(dev);
}
+ /* configure PCIe to RC mode */
+ msm_pcie_write_reg(dev->parf, PCIE20_PARF_DEVICE_TYPE, 0x4);
+
+ /* enable l1 mode, clear bit 5 (REQ_NOT_ENTR_L1) */
+ if (dev->l1_supported)
+ msm_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, BIT(5), 0);
+
/* enable PCIe clocks and resets */
msm_pcie_write_mask(dev->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0);
@@ -4688,6 +3854,9 @@
msm_pcie_config_link_state(dev);
+ if (dev->enumerated)
+ pci_walk_bus(dev->dev->bus, &msm_pcie_config_device, dev);
+
dev->link_status = MSM_PCIE_LINK_ENABLED;
dev->power_on = true;
dev->suspending = false;
@@ -4935,106 +4104,41 @@
return ret;
}
-int msm_pcie_configure_sid(struct device *dev, u32 *sid, int *domain)
+static void msm_pcie_configure_sid(struct msm_pcie_dev_t *pcie_dev,
+ struct pci_dev *dev)
{
- struct pci_dev *pcidev;
- struct msm_pcie_dev_t *pcie_dev;
- struct pci_bus *bus;
- int i;
+ u32 offset;
+ u32 sid;
u32 bdf;
+ int ret;
- if (!dev) {
- pr_err("%s: PCIe: endpoint device passed in is NULL\n",
- __func__);
- return MSM_PCIE_ERROR;
- }
-
- pcidev = to_pci_dev(dev);
- if (!pcidev) {
- pr_err("%s: PCIe: PCI device of endpoint is NULL\n",
- __func__);
- return MSM_PCIE_ERROR;
- }
-
- bus = pcidev->bus;
- if (!bus) {
- pr_err("%s: PCIe: Bus of PCI device is NULL\n",
- __func__);
- return MSM_PCIE_ERROR;
- }
-
- while (!pci_is_root_bus(bus))
- bus = bus->parent;
-
- pcie_dev = (struct msm_pcie_dev_t *)(bus->sysdata);
- if (!pcie_dev) {
- pr_err("%s: PCIe: Could not get PCIe structure\n",
- __func__);
- return MSM_PCIE_ERROR;
- }
-
- if (!pcie_dev->smmu_exist) {
+ ret = iommu_fwspec_get_id(&dev->dev, &sid);
+ if (ret) {
PCIE_DBG(pcie_dev,
- "PCIe: RC:%d: smmu does not exist\n",
+ "PCIe: RC%d: Device does not have a SID\n",
pcie_dev->rc_idx);
- return MSM_PCIE_ERROR;
- }
-
- PCIE_DBG(pcie_dev, "PCIe: RC%d: device address is: %p\n",
- pcie_dev->rc_idx, dev);
- PCIE_DBG(pcie_dev, "PCIe: RC%d: PCI device address is: %p\n",
- pcie_dev->rc_idx, pcidev);
-
- *domain = pcie_dev->rc_idx;
-
- if (pcie_dev->current_short_bdf < (MAX_SHORT_BDF_NUM - 1)) {
- pcie_dev->current_short_bdf++;
- } else {
- PCIE_ERR(pcie_dev,
- "PCIe: RC%d: No more short BDF left\n",
- pcie_dev->rc_idx);
- return MSM_PCIE_ERROR;
- }
-
- bdf = BDF_OFFSET(pcidev->bus->number, pcidev->devfn);
-
- for (i = 0; i < MAX_DEVICE_NUM; i++) {
- if (pcie_dev->pcidev_table[i].bdf == bdf) {
- *sid = pcie_dev->smmu_sid_base +
- ((pcie_dev->rc_idx << 4) |
- pcie_dev->current_short_bdf);
-
- msm_pcie_write_reg(pcie_dev->parf,
- PCIE20_PARF_BDF_TRANSLATE_N +
- pcie_dev->current_short_bdf * 4,
- bdf >> 16);
-
- pcie_dev->pcidev_table[i].sid = *sid;
- pcie_dev->pcidev_table[i].short_bdf =
- pcie_dev->current_short_bdf;
- break;
- }
- }
-
- if (i == MAX_DEVICE_NUM) {
- pcie_dev->current_short_bdf--;
- PCIE_ERR(pcie_dev,
- "PCIe: RC%d could not find BDF:%d\n",
- pcie_dev->rc_idx, bdf);
- return MSM_PCIE_ERROR;
+ return;
}
PCIE_DBG(pcie_dev,
- "PCIe: RC%d: Device: %02x:%02x.%01x received SID %d\n",
- pcie_dev->rc_idx,
- bdf >> 24,
- bdf >> 19 & 0x1f,
- bdf >> 16 & 0x07,
- *sid);
+ "PCIe: RC%d: Device SID: 0x%x\n",
+ pcie_dev->rc_idx, sid);
- return 0;
+ bdf = BDF_OFFSET(dev->bus->number, dev->devfn);
+ offset = (sid - pcie_dev->smmu_sid_base) * 4;
+
+ if (offset >= MAX_SHORT_BDF_NUM * 4) {
+ PCIE_ERR(pcie_dev,
+ "PCIe: RC%d: Invalid SID offset: 0x%x. Should be less than 0x%x\n",
+ pcie_dev->rc_idx, offset, MAX_SHORT_BDF_NUM * 4);
+ return;
+ }
+
+ msm_pcie_write_reg(pcie_dev->parf, PCIE20_PARF_BDF_TRANSLATE_CFG, 0);
+ msm_pcie_write_reg(pcie_dev->parf, PCIE20_PARF_SID_OFFSET, 0);
+ msm_pcie_write_reg(pcie_dev->parf,
+ PCIE20_PARF_BDF_TRANSLATE_N + offset, bdf >> 16);
}
-EXPORT_SYMBOL(msm_pcie_configure_sid);
int msm_pcie_enumerate(u32 rc_idx)
{
@@ -6138,6 +5242,28 @@
disable_irq(dev->wake_n);
}
+static int msm_pcie_config_device(struct pci_dev *dev, void *pdev)
+{
+ struct msm_pcie_dev_t *pcie_dev = (struct msm_pcie_dev_t *)pdev;
+ u8 busnr = dev->bus->number;
+ u8 slot = PCI_SLOT(dev->devfn);
+ u8 func = PCI_FUNC(dev->devfn);
+
+ PCIE_DBG(pcie_dev, "PCIe: RC%d: configure PCI device %02x:%02x.%01x\n",
+ pcie_dev->rc_idx, busnr, slot, func);
+
+ msm_pcie_configure_sid(pcie_dev, dev);
+
+ return 0;
+}
+
+/* Hook to setup PCI device during PCI framework scan */
+int pcibios_add_device(struct pci_dev *dev)
+{
+ struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev->bus);
+
+ return msm_pcie_config_device(dev, pcie_dev);
+}
static int msm_pcie_probe(struct platform_device *pdev)
{
@@ -6413,7 +5539,6 @@
msm_pcie_dev[rc_idx].wake_counter = 0;
msm_pcie_dev[rc_idx].aer_enable = true;
msm_pcie_dev[rc_idx].power_on = false;
- msm_pcie_dev[rc_idx].current_short_bdf = 0;
msm_pcie_dev[rc_idx].use_msi = false;
msm_pcie_dev[rc_idx].use_pinctrl = false;
msm_pcie_dev[rc_idx].linkdown_panic = false;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index af4d4c8..fb42ef7 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -3679,6 +3679,7 @@
* pipe will be unsuspended as part of
* enabling IPA clocks
*/
+ mutex_lock(&ipa_ctx->sps_pm.sps_pm_lock);
if (!atomic_read(
&ipa_ctx->sps_pm.dec_clients)
) {
@@ -3691,6 +3692,7 @@
1);
ipa_sps_process_irq_schedule_rel();
}
+ mutex_unlock(&ipa_ctx->sps_pm.sps_pm_lock);
} else {
resource = ipa2_get_rm_resource_from_ep(i);
res = ipa_rm_request_resource_with_timer(
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 83fd2b2..30f5712 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -3620,6 +3620,8 @@
* pipe will be unsuspended as part of
* enabling IPA clocks
*/
+ mutex_lock(&ipa3_ctx->transport_pm.
+ transport_pm_mutex);
if (!atomic_read(
&ipa3_ctx->transport_pm.dec_clients)
) {
@@ -3632,6 +3634,8 @@
1);
ipa3_process_irq_schedule_rel();
}
+ mutex_unlock(&ipa3_ctx->transport_pm.
+ transport_pm_mutex);
} else {
resource = ipa3_get_rm_resource_from_ep(i);
res =
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 69e3032..3311380 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -655,3 +655,11 @@
memory location. These messages provide statistical information about
the low power modes that RPM enters. The drivers outputs the message
via a debugfs node.
+
+config QCOM_FORCE_WDOG_BITE_ON_PANIC
+ bool "QCOM force watchdog bite"
+ depends on QCOM_WATCHDOG_V2
+ help
+ This forces a watchdog bite when the device restarts due to a
+ kernel panic. On certain MSM SoCs, this provides us
+ additional debugging information.
diff --git a/drivers/soc/qcom/glink_private.h b/drivers/soc/qcom/glink_private.h
index c837bd8..9810207 100644
--- a/drivers/soc/qcom/glink_private.h
+++ b/drivers/soc/qcom/glink_private.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -700,6 +700,7 @@
* edge: The G-Link edge name for the channel associated with
* this callback data
* do_cleanup_data: Structure containing the G-Link SSR do_cleanup message.
+ * cb_kref: Kref object to maintain cb_data reference.
*/
struct ssr_notify_data {
bool tx_done;
@@ -707,6 +708,7 @@
bool responded;
const char *edge;
struct do_cleanup_msg *do_cleanup_data;
+ struct kref cb_kref;
};
/**
@@ -741,6 +743,7 @@
int notify_list_len;
bool link_up;
spinlock_t link_up_lock;
+ spinlock_t cb_lock;
};
/**
diff --git a/drivers/soc/qcom/glink_ssr.c b/drivers/soc/qcom/glink_ssr.c
index b24598a..4737288 100644
--- a/drivers/soc/qcom/glink_ssr.c
+++ b/drivers/soc/qcom/glink_ssr.c
@@ -115,6 +115,44 @@
static atomic_t responses_remaining = ATOMIC_INIT(0);
static wait_queue_head_t waitqueue;
+/**
+ * cb_data_release() - Free cb_data and set to NULL
+ * @kref_ptr: pointer to kref.
+ *
+ * This function releses cb_data.
+ */
+static inline void cb_data_release(struct kref *kref_ptr)
+{
+ struct ssr_notify_data *cb_data;
+
+ cb_data = container_of(kref_ptr, struct ssr_notify_data, cb_kref);
+ kfree(cb_data);
+}
+
+/**
+ * check_and_get_cb_data() - Try to get reference to kref of cb_data
+ * @ss_info: pointer to subsystem info structure.
+ *
+ * Return: NULL is cb_data is NULL, pointer to cb_data otherwise
+ */
+static struct ssr_notify_data *check_and_get_cb_data(
+ struct subsys_info *ss_info)
+{
+ struct ssr_notify_data *cb_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ss_info->cb_lock, flags);
+ if (ss_info->cb_data == NULL) {
+ GLINK_SSR_LOG("<SSR> %s: cb_data is NULL\n", __func__);
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
+ return 0;
+ }
+ kref_get(&ss_info->cb_data->cb_kref);
+ cb_data = ss_info->cb_data;
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
+ return cb_data;
+}
+
static void rx_done_cb_worker(struct work_struct *work)
{
struct rx_done_ch_work *rx_done_work =
@@ -340,8 +378,10 @@
if (WARN_ON(!ss_info->cb_data))
return;
- kfree(ss_info->cb_data);
+ spin_lock_irqsave(&ss_info->cb_lock, flags);
+ kref_put(&ss_info->cb_data->cb_kref, cb_data_release);
ss_info->cb_data = NULL;
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
kfree(close_work);
}
@@ -508,13 +548,18 @@
return -ENODEV;
}
handle = ss_info_channel->handle;
- ss_leaf_entry->cb_data = ss_info_channel->cb_data;
+ ss_leaf_entry->cb_data = check_and_get_cb_data(
+ ss_info_channel);
+ if (!ss_leaf_entry->cb_data) {
+ GLINK_SSR_LOG("<SSR> %s: CB data is NULL\n", __func__);
+ atomic_dec(&responses_remaining);
+ continue;
+ }
spin_lock_irqsave(&ss_info->link_up_lock, flags);
if (IS_ERR_OR_NULL(ss_info_channel->handle) ||
- !ss_info_channel->cb_data ||
!ss_info_channel->link_up ||
- ss_info_channel->cb_data->event
+ ss_leaf_entry->cb_data->event
!= GLINK_CONNECTED) {
GLINK_SSR_LOG(
@@ -527,6 +572,8 @@
spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
atomic_dec(&responses_remaining);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
continue;
}
spin_unlock_irqrestore(&ss_info->link_up_lock, flags);
@@ -537,6 +584,8 @@
GLINK_SSR_ERR(
"%s %s: Could not allocate do_cleanup_msg\n",
"<SSR>", __func__);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
return -ENOMEM;
}
@@ -568,6 +617,8 @@
__func__);
}
atomic_dec(&responses_remaining);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
continue;
}
@@ -597,10 +648,12 @@
__func__);
}
atomic_dec(&responses_remaining);
+ kref_put(&ss_leaf_entry->cb_data->cb_kref,
+ cb_data_release);
continue;
}
-
sequence_number++;
+ kref_put(&ss_leaf_entry->cb_data->cb_kref, cb_data_release);
}
wait_ret = wait_event_timeout(waitqueue,
@@ -609,6 +662,21 @@
list_for_each_entry(ss_leaf_entry, &ss_info->notify_list,
notify_list_node) {
+ ss_info_channel =
+ get_info_for_subsystem(ss_leaf_entry->ssr_name);
+ if (ss_info_channel == NULL) {
+ GLINK_SSR_ERR(
+ "<SSR> %s: unable to find subsystem name\n",
+ __func__);
+ continue;
+ }
+
+ ss_leaf_entry->cb_data = check_and_get_cb_data(
+ ss_info_channel);
+ if (!ss_leaf_entry->cb_data) {
+ GLINK_SSR_LOG("<SSR> %s: CB data is NULL\n", __func__);
+ continue;
+ }
if (!wait_ret && !IS_ERR_OR_NULL(ss_leaf_entry->cb_data)
&& !ss_leaf_entry->cb_data->responded) {
GLINK_SSR_ERR("%s %s: Subsystem %s %s\n",
@@ -627,6 +695,7 @@
if (!IS_ERR_OR_NULL(ss_leaf_entry->cb_data))
ss_leaf_entry->cb_data->responded = false;
+ kref_put(&ss_leaf_entry->cb_data->cb_kref, cb_data_release);
}
complete(¬ifications_successful_complete);
return 0;
@@ -645,6 +714,7 @@
struct glink_open_config open_cfg;
struct ssr_notify_data *cb_data = NULL;
void *handle = NULL;
+ unsigned long flags;
if (!ss_info) {
GLINK_SSR_ERR("<SSR> %s: ss_info structure invalid\n",
@@ -661,7 +731,10 @@
cb_data->responded = false;
cb_data->event = GLINK_SSR_EVENT_INIT;
cb_data->edge = ss_info->edge;
+ spin_lock_irqsave(&ss_info->cb_lock, flags);
ss_info->cb_data = cb_data;
+ kref_init(&cb_data->cb_kref);
+ spin_unlock_irqrestore(&ss_info->cb_lock, flags);
memset(&open_cfg, 0, sizeof(struct glink_open_config));
@@ -877,6 +950,7 @@
ss_info->link_state_handle = NULL;
ss_info->cb_data = NULL;
spin_lock_init(&ss_info->link_up_lock);
+ spin_lock_init(&ss_info->cb_lock);
nb = kmalloc(sizeof(struct restart_notifier_block), GFP_KERNEL);
if (!nb) {
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index e30c159..b9070bd 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -12,6 +12,7 @@
*/
#include <linux/atomic.h>
+#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@ -70,6 +71,7 @@
struct rpmh_msg *msg_pool;
DECLARE_BITMAP(fast_req, RPMH_MAX_FAST_RES);
bool dirty;
+ bool in_solver_mode;
};
struct rpmh_client {
@@ -458,10 +460,21 @@
int count = 0;
int ret, i, j, k;
bool complete_set;
+ unsigned long flags;
+ struct rpmh_mbox *rpm;
if (rpmh_standalone)
return 0;
+ /* Do not allow setting wake votes when in solver mode */
+ rpm = rc->rpmh;
+ spin_lock_irqsave(&rpm->lock, flags);
+ if (rpm->in_solver_mode && state == RPMH_WAKE_ONLY_STATE) {
+ spin_unlock_irqrestore(&rpm->lock, flags);
+ return -EIO;
+ }
+ spin_unlock_irqrestore(&rpm->lock, flags);
+
while (n[count++])
;
count--;
@@ -526,6 +539,43 @@
EXPORT_SYMBOL(rpmh_write_passthru);
/**
+ * rpmh_mode_solver_set: Indicate that the RSC controller hardware has
+ * been configured to be in solver mode
+ *
+ * @rc: The RPMH handle
+ * @enable: Boolean value indicating if the controller is in solver mode.
+ *
+ * When solver mode is enabled, passthru API will not be able to send wake
+ * votes, just awake and active votes.
+ */
+int rpmh_mode_solver_set(struct rpmh_client *rc, bool enable)
+{
+ struct rpmh_mbox *rpm;
+ unsigned long flags;
+
+ if (IS_ERR_OR_NULL(rc))
+ return -EINVAL;
+
+ if (rpmh_standalone)
+ return 0;
+
+ rpm = rc->rpmh;
+ do {
+ spin_lock_irqsave(&rpm->lock, flags);
+ if (mbox_controller_is_idle(rc->chan)) {
+ rpm->in_solver_mode = enable;
+ spin_unlock_irqrestore(&rpm->lock, flags);
+ break;
+ }
+ spin_unlock_irqrestore(&rpm->lock, flags);
+ udelay(10);
+ } while (1);
+
+ return 0;
+}
+EXPORT_SYMBOL(rpmh_mode_solver_set);
+
+/**
* rpmh_write_control: Write async control commands to the controller
*
* @rc: The RPMh handle got from rpmh_get_dev_channel
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index df9be34..3fec1d7 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <linux/console.h>
#include <linux/io.h>
+#include <linux/ipc_logging.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -41,7 +42,7 @@
#define SE_UART_RX_STALE_CNT (0x294)
#define SE_UART_TX_PARITY_CFG (0x2A4)
#define SE_UART_RX_PARITY_CFG (0x2A8)
-#define SE_UART_MANUAL_RFT (0x2AC)
+#define SE_UART_MANUAL_RFR (0x2AC)
/* SE_UART_LOOPBACK_CFG */
#define NO_LOOPBACK (0)
@@ -84,6 +85,11 @@
#define PAR_SPACE (0x10)
#define PAR_MARK (0x11)
+/* SE_UART_MANUAL_RFR register fields */
+#define UART_MANUAL_RFR_EN (BIT(31))
+#define UART_RFR_NOT_READY (BIT(1))
+#define UART_RFR_READY (BIT(0))
+
/* UART M_CMD OP codes */
#define UART_START_TX (0x1)
#define UART_START_BREAK (0x4)
@@ -94,13 +100,26 @@
#define UART_OVERSAMPLING (32)
#define STALE_TIMEOUT (16)
+#define DEFAULT_BITS_PER_CHAR (10)
#define GENI_UART_NR_PORTS (15)
+#define GENI_UART_CONS_PORTS (1)
#define DEF_FIFO_DEPTH_WORDS (16)
+#define DEF_TX_WM (2)
#define DEF_FIFO_WIDTH_BITS (32)
#define UART_CORE2X_VOTE (10000)
#define DEFAULT_SE_CLK (19200000)
#define DEFAULT_BUS_WIDTH (4)
+#define WAKEBYTE_TIMEOUT_MSEC (2000)
+#define IPC_LOG_PWR_PAGES (2)
+#define IPC_LOG_MISC_PAGES (2)
+#define IPC_LOG_TX_RX_PAGES (3)
+#define DATA_BYTES_PER_LINE (32)
+
+#define IPC_LOG_MSG(ctx, x...) do { \
+ if (ctx) \
+ ipc_log_string(ctx, x); \
+} while (0)
struct msm_geni_serial_port {
struct uart_port uport;
@@ -121,6 +140,14 @@
unsigned int rx_last);
struct se_geni_rsc serial_rsc;
int loopback;
+ int wakeup_irq;
+ unsigned char wakeup_byte;
+ struct wakeup_source geni_wake;
+ void *ipc_log_tx;
+ void *ipc_log_rx;
+ void *ipc_log_pwr;
+ void *ipc_log_misc;
+ unsigned int cur_baud;
};
static const struct uart_ops msm_geni_serial_pops;
@@ -134,12 +161,16 @@
unsigned int rx_fifo_wc,
unsigned int rx_last_byte_valid,
unsigned int rx_last);
+static unsigned int msm_geni_serial_tx_empty(struct uart_port *port);
+static int msm_geni_serial_power_on(struct uart_port *uport);
+static void msm_geni_serial_power_off(struct uart_port *uport);
static atomic_t uart_line_id = ATOMIC_INIT(0);
#define GET_DEV_PORT(uport) \
container_of(uport, struct msm_geni_serial_port, uport)
+static struct msm_geni_serial_port msm_geni_console_port;
static struct msm_geni_serial_port msm_geni_serial_ports[GENI_UART_NR_PORTS];
static void msm_geni_serial_config_port(struct uart_port *uport, int cfg_flags)
@@ -174,22 +205,172 @@
static DEVICE_ATTR(loopback, 0644, msm_geni_serial_loopback_show,
msm_geni_serial_loopback_store);
-static void msm_geni_serial_set_mctrl(struct uart_port *port,
+static void dump_ipc(void *ipc_ctx, char *prefix, char *string,
+ u64 addr, int size)
+
+{
+ char buf[DATA_BYTES_PER_LINE * 2];
+ int len = 0;
+
+ if (!ipc_ctx)
+ return;
+ len = min(size, DATA_BYTES_PER_LINE);
+ hex_dump_to_buffer(string, len, DATA_BYTES_PER_LINE, 1, buf,
+ sizeof(buf), false);
+ ipc_log_string(ipc_ctx, "%s[0x%.10x:%d] : %s", prefix,
+ (unsigned int)addr, size, buf);
+}
+
+static void check_tx_active(struct uart_port *uport)
+{
+ u32 geni_status = geni_read_reg_nolog(uport->membase,
+ SE_GENI_STATUS);
+
+ while ((geni_status & M_GENI_CMD_ACTIVE)) {
+ cpu_relax();
+ geni_status = geni_read_reg_nolog(uport->membase,
+ SE_GENI_STATUS);
+ }
+}
+
+static int vote_clock_on(struct uart_port *uport)
+{
+ int ret = 0;
+ struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+
+ if (!pm_runtime_enabled(uport->dev)) {
+ dev_err(uport->dev, "RPM not available.Can't enable clocks\n");
+ ret = -EPERM;
+ return ret;
+ }
+ ret = msm_geni_serial_power_on(uport);
+ if (ret) {
+ dev_err(uport->dev, "Failed to vote clock on\n");
+ return ret;
+ }
+ __pm_relax(&port->geni_wake);
+ IPC_LOG_MSG(port->ipc_log_pwr, "%s\n", __func__);
+ return 0;
+}
+
+static int vote_clock_off(struct uart_port *uport)
+{
+ struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+ int ret = 0;
+
+ if (!pm_runtime_enabled(uport->dev)) {
+ dev_err(uport->dev, "RPM not available.Can't enable clocks\n");
+ ret = -EPERM;
+ return ret;
+ }
+ /* Block till any on going Tx goes out.*/
+ check_tx_active(uport);
+ msm_geni_serial_power_off(uport);
+ IPC_LOG_MSG(port->ipc_log_pwr, "%s\n", __func__);
+ return 0;
+};
+
+static int msm_geni_serial_ioctl(struct uart_port *uport, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -ENOIOCTLCMD;
+
+ switch (cmd) {
+ case TIOCPMGET: {
+ ret = vote_clock_on(uport);
+ break;
+ }
+ case TIOCPMPUT: {
+ ret = vote_clock_off(uport);
+ break;
+ }
+ case TIOCPMACT: {
+ ret = !pm_runtime_status_suspended(uport->dev);
+ break;
+ }
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_geni_serial_break_ctl(struct uart_port *uport, int ctl)
+{
+ if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
+ dev_err(uport->dev, "%s Device suspended,vote clocks on.\n",
+ __func__);
+ return;
+ }
+
+ if (ctl) {
+ check_tx_active(uport);
+ geni_setup_m_cmd(uport->membase, UART_START_BREAK, 0);
+ } else {
+ geni_setup_m_cmd(uport->membase, UART_STOP_BREAK, 0);
+ }
+ /* Ensure break start/stop command is setup before returning.*/
+ mb();
+}
+
+static unsigned int msm_geni_serial_get_mctrl(struct uart_port *uport)
+{
+ u32 geni_ios = 0;
+ unsigned int mctrl = TIOCM_DSR | TIOCM_CAR;
+
+ if (pm_runtime_status_suspended(uport->dev))
+ return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS;
+
+ geni_ios = geni_read_reg_nolog(uport->membase, SE_GENI_IOS);
+ if (!(geni_ios & IO2_DATA_IN))
+ mctrl |= TIOCM_CTS;
+
+ return mctrl;
+}
+
+static void msm_geni_cons_set_mctrl(struct uart_port *uport,
unsigned int mctrl)
{
}
+static void msm_geni_serial_set_mctrl(struct uart_port *uport,
+ unsigned int mctrl)
+{
+ u32 uart_manual_rfr = 0;
+
+ if (pm_runtime_status_suspended(uport->dev)) {
+ dev_info(uport->dev, "%sDevice suspended,vote clocks on\n",
+ __func__);
+ return;
+ }
+ if (!(mctrl & TIOCM_RTS))
+ uart_manual_rfr |= (UART_MANUAL_RFR_EN | UART_RFR_NOT_READY);
+ geni_write_reg_nolog(uart_manual_rfr, uport->membase,
+ SE_UART_MANUAL_RFR);
+ /* Write to flow control must complete before return to client*/
+ mb();
+}
+
static const char *msm_geni_serial_get_type(struct uart_port *uport)
{
return "MSM";
}
-static struct msm_geni_serial_port *get_port_from_line(int line)
+static struct msm_geni_serial_port *get_port_from_line(int line,
+ bool is_console)
{
- if ((line < 0) || (line >= GENI_UART_NR_PORTS))
- return ERR_PTR(-ENXIO);
+ struct msm_geni_serial_port *port = NULL;
- return &msm_geni_serial_ports[line];
+ if (is_console) {
+ if ((line < 0) || (line >= GENI_UART_CONS_PORTS))
+ port = ERR_PTR(-ENXIO);
+ port = &msm_geni_console_port;
+ } else {
+ if ((line < 0) || (line >= GENI_UART_NR_PORTS))
+ return ERR_PTR(-ENXIO);
+ port = &msm_geni_serial_ports[line];
+ }
+
+ return port;
}
static int msm_geni_serial_power_on(struct uart_port *uport)
@@ -200,14 +381,15 @@
if (ret < 0) {
dev_err(uport->dev, "%s: Failed (%d)", __func__, ret);
pm_runtime_put_noidle(uport->dev);
+ pm_runtime_set_suspended(uport->dev);
+ return ret;
}
- return ret;
+ return 0;
}
static void msm_geni_serial_power_off(struct uart_port *uport)
{
- pm_runtime_mark_last_busy(uport->dev);
- pm_runtime_put_autosuspend(uport->dev);
+ pm_runtime_put_sync(uport->dev);
}
static int msm_geni_serial_poll_bit(struct uart_port *uport,
@@ -216,9 +398,26 @@
int iter = 0;
unsigned int reg;
bool met = false;
+ struct msm_geni_serial_port *port = NULL;
bool cond = false;
+ unsigned int baud = 115200;
+ unsigned int fifo_bits = DEF_FIFO_DEPTH_WORDS * DEF_FIFO_WIDTH_BITS;
+ unsigned long total_iter = 0;
- while (iter < 1000) {
+
+ if (uport->private_data) {
+ port = GET_DEV_PORT(uport);
+ baud = (port->cur_baud ? port->cur_baud : 115200);
+ fifo_bits = port->tx_fifo_depth * port->tx_fifo_width;
+ }
+ /*
+ * Total polling iterations based on FIFO worth of bytes to be
+ * sent at current baud .Add a little fluff to the wait.
+ */
+ total_iter = ((fifo_bits * USEC_PER_SEC) / baud);
+ total_iter += 50;
+
+ while (iter < total_iter) {
reg = geni_read_reg_nolog(uport->membase, offset);
cond = reg & bit_field;
if (cond == set) {
@@ -232,7 +431,7 @@
}
static void msm_geni_serial_setup_tx(struct uart_port *uport,
- unsigned int xmit_size)
+ unsigned int xmit_size)
{
u32 m_cmd = 0;
@@ -299,8 +498,10 @@
SE_GENI_M_IRQ_STATUS);
s_irq_status = geni_read_reg_nolog(uport->membase,
SE_GENI_S_IRQ_STATUS);
- geni_write_reg_nolog(m_irq_status, uport->membase, SE_GENI_M_IRQ_CLEAR);
- geni_write_reg_nolog(s_irq_status, uport->membase, SE_GENI_S_IRQ_CLEAR);
+ geni_write_reg_nolog(m_irq_status, uport->membase,
+ SE_GENI_M_IRQ_CLEAR);
+ geni_write_reg_nolog(s_irq_status, uport->membase,
+ SE_GENI_S_IRQ_CLEAR);
if (!(msm_geni_serial_poll_bit(uport, SE_GENI_RX_FIFO_STATUS,
RX_FIFO_WC_MSK, true))) {
@@ -324,7 +525,6 @@
int b = (int) c;
struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
- se_config_packing(uport->membase, 8, 1, false);
geni_write_reg_nolog(port->tx_wm, uport->membase,
SE_GENI_TX_WATERMARK_REG);
msm_geni_serial_setup_tx(uport, 1);
@@ -358,10 +558,11 @@
__msm_geni_serial_console_write(struct uart_port *uport, const char *s,
unsigned int count)
{
- struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
int new_line = 0;
int i;
int bytes_to_send = count;
+ int fifo_depth = DEF_FIFO_DEPTH_WORDS;
+ int tx_wm = DEF_TX_WM;
for (i = 0; i < count; i++) {
if (s[i] == '\n')
@@ -369,14 +570,13 @@
}
bytes_to_send += new_line;
- se_config_packing(uport->membase, 8, 1, false);
- geni_write_reg_nolog(port->tx_wm, uport->membase,
+ geni_write_reg_nolog(tx_wm, uport->membase,
SE_GENI_TX_WATERMARK_REG);
msm_geni_serial_setup_tx(uport, bytes_to_send);
i = 0;
while (i < count) {
u32 chars_to_write = 0;
- u32 avail_fifo_bytes = (port->tx_fifo_depth - port->tx_wm);
+ u32 avail_fifo_bytes = (fifo_depth - tx_wm);
/*
* If the WM bit never set, then the Tx state machine is not
* in a valid state, so break, cancel/abort any existing
@@ -409,7 +609,7 @@
WARN_ON(co->index < 0 || co->index >= GENI_UART_NR_PORTS);
- port = get_port_from_line(co->index);
+ port = get_port_from_line(co->index, true);
if (IS_ERR_OR_NULL(port)) {
pr_err("%s:Invalid line %d\n", __func__, co->index);
return;
@@ -432,7 +632,6 @@
struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
tport = &uport->state->port;
-
for (i = 0; i < rx_fifo_wc; i++) {
int bytes = 4;
@@ -471,23 +670,35 @@
static void msm_geni_serial_start_tx(struct uart_port *uport)
{
unsigned int geni_m_irq_en;
- struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+ struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+
+ if (!msm_geni_serial_tx_empty(uport))
+ return;
+
+ if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
+ dev_err(uport->dev, "%s.Device is suspended.\n", __func__);
+ return;
+ }
geni_m_irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN);
geni_m_irq_en |= M_TX_FIFO_WATERMARK_EN;
- se_config_packing(uport->membase, 8, 4, false);
- geni_write_reg_nolog(port->tx_wm, uport->membase,
+ geni_write_reg_nolog(msm_port->tx_wm, uport->membase,
SE_GENI_TX_WATERMARK_REG);
geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN);
/* Geni command setup/irq enables should complete before returning.*/
mb();
+ IPC_LOG_MSG(msm_port->ipc_log_misc, "%s\n", __func__);
}
static void msm_geni_serial_stop_tx(struct uart_port *uport)
{
unsigned int geni_m_irq_en;
unsigned int geni_status;
+ struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+
+ if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+ return;
geni_m_irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN);
geni_m_irq_en &= ~(M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN);
@@ -510,21 +721,34 @@
SE_GENI_M_IRQ_CLEAR);
}
geni_write_reg_nolog(M_CMD_CANCEL_EN, uport, SE_GENI_M_IRQ_CLEAR);
+ IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__);
}
static void msm_geni_serial_start_rx(struct uart_port *uport)
{
unsigned int geni_s_irq_en;
unsigned int geni_m_irq_en;
+ unsigned long cfg0, cfg1;
+ unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT;
+ unsigned int geni_status;
+ struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
- msm_geni_serial_abort_rx(uport);
+ if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+ return;
+
+ geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
+ if (geni_status & S_GENI_CMD_ACTIVE)
+ msm_geni_serial_abort_rx(uport);
geni_s_irq_en = geni_read_reg_nolog(uport->membase,
SE_GENI_S_IRQ_EN);
geni_m_irq_en = geni_read_reg_nolog(uport->membase,
SE_GENI_M_IRQ_EN);
geni_s_irq_en |= S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN;
geni_m_irq_en |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
-
+ se_get_packing_config(8, 4, false, &cfg0, &cfg1);
+ geni_write_reg_nolog(cfg0, uport->membase, SE_GENI_RX_PACKING_CFG0);
+ geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_RX_PACKING_CFG1);
+ geni_write_reg_nolog(rxstale, uport->membase, SE_UART_RX_STALE_CNT);
geni_setup_s_cmd(uport->membase, UART_START_READ, 0);
geni_write_reg_nolog(geni_s_irq_en, uport->membase, SE_GENI_S_IRQ_EN);
geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN);
@@ -533,6 +757,7 @@
* go through.
*/
mb();
+ IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__);
}
static void msm_geni_serial_stop_rx(struct uart_port *uport)
@@ -541,6 +766,9 @@
unsigned int geni_m_irq_en;
unsigned int geni_status;
+ if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+ return;
+
geni_s_irq_en = geni_read_reg_nolog(uport->membase,
SE_GENI_S_IRQ_EN);
geni_m_irq_en = geni_read_reg_nolog(uport->membase,
@@ -586,6 +814,8 @@
}
uport->icount.rx += ret;
tty_flip_buffer_push(tport);
+ dump_ipc(msm_port->ipc_log_rx, "Rx", (char *)msm_port->rx_fifo, 0,
+ rx_bytes);
return ret;
}
@@ -597,7 +827,7 @@
unsigned int rx_last_byte_valid = 0;
unsigned int rx_last = 0;
struct tty_port *tport;
- struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+ struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
tport = &uport->state->port;
rx_fifo_status = geni_read_reg_nolog(uport->membase,
@@ -607,7 +837,7 @@
RX_LAST_BYTE_VALID_SHFT);
rx_last = rx_fifo_status & RX_LAST;
if (rx_fifo_wc)
- msm_port->handle_rx(uport, rx_fifo_wc, rx_last_byte_valid,
+ port->handle_rx(uport, rx_fifo_wc, rx_last_byte_valid,
rx_last);
return ret;
}
@@ -622,7 +852,8 @@
int i = 0;
unsigned int tx_fifo_status;
unsigned int xmit_size;
- unsigned int fifo_width_bytes = msm_port->tx_fifo_width >> 3;
+ unsigned int fifo_width_bytes =
+ (uart_console(uport) ? 1 : (msm_port->tx_fifo_width >> 3));
tx_fifo_status = geni_read_reg_nolog(uport->membase,
SE_GENI_TX_FIFO_STATUS);
@@ -645,6 +876,8 @@
msm_geni_serial_setup_tx(uport, xmit_size);
bytes_remaining = xmit_size;
+ dump_ipc(msm_port->ipc_log_tx, "Tx", (char *)&xmit->buf[xmit->tail], 0,
+ xmit_size);
while (i < xmit_size) {
unsigned int tx_bytes;
unsigned int buf = 0;
@@ -664,6 +897,8 @@
wmb();
}
msm_geni_serial_poll_cancel_tx(uport);
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(uport);
exit_handle_tx:
return ret;
}
@@ -676,12 +911,18 @@
unsigned long flags;
spin_lock_irqsave(&uport->lock, flags);
+ if (uart_console(uport) && uport->suspended)
+ goto exit_geni_serial_isr;
+ if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+ goto exit_geni_serial_isr;
m_irq_status = geni_read_reg_nolog(uport->membase,
- SE_GENI_M_IRQ_STATUS);
+ SE_GENI_M_IRQ_STATUS);
s_irq_status = geni_read_reg_nolog(uport->membase,
- SE_GENI_S_IRQ_STATUS);
- geni_write_reg_nolog(m_irq_status, uport->membase, SE_GENI_M_IRQ_CLEAR);
- geni_write_reg_nolog(s_irq_status, uport->membase, SE_GENI_S_IRQ_CLEAR);
+ SE_GENI_S_IRQ_STATUS);
+ geni_write_reg_nolog(m_irq_status, uport->membase,
+ SE_GENI_M_IRQ_CLEAR);
+ geni_write_reg_nolog(s_irq_status, uport->membase,
+ SE_GENI_S_IRQ_CLEAR);
if ((m_irq_status & M_ILLEGAL_CMD_EN)) {
WARN_ON(1);
@@ -701,6 +942,28 @@
return IRQ_HANDLED;
}
+static irqreturn_t msm_geni_wakeup_isr(int isr, void *dev)
+{
+ struct uart_port *uport = dev;
+ struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+ struct tty_struct *tty;
+ unsigned long flags;
+
+ spin_lock_irqsave(&uport->lock, flags);
+ if (port->wakeup_byte) {
+ tty = uport->state->port.tty;
+ tty_insert_flip_char(tty->port, port->wakeup_byte, TTY_NORMAL);
+ IPC_LOG_MSG(port->ipc_log_rx, "%s: Inject 0x%x\n",
+ __func__, port->wakeup_byte);
+ tty_flip_buffer_push(tty->port);
+ }
+ __pm_wakeup_event(&port->geni_wake, WAKEBYTE_TIMEOUT_MSEC);
+ IPC_LOG_MSG(port->ipc_log_misc, "%s:Holding Wake Lock for %d ms\n",
+ __func__, WAKEBYTE_TIMEOUT_MSEC);
+ spin_unlock_irqrestore(&uport->lock, flags);
+ return IRQ_HANDLED;
+}
+
static int get_tx_fifo_size(struct msm_geni_serial_port *port)
{
struct uart_port *uport;
@@ -755,33 +1018,89 @@
msm_geni_serial_stop_rx(uport);
disable_irq(uport->irq);
free_irq(uport->irq, msm_port);
- if (uart_console(uport))
+ if (uart_console(uport)) {
se_geni_resources_off(&msm_port->serial_rsc);
- else
+ } else {
+ if (msm_port->wakeup_irq > 0) {
+ disable_irq(msm_port->wakeup_irq);
+ free_irq(msm_port->wakeup_irq, msm_port);
+ }
+ __pm_relax(&msm_port->geni_wake);
msm_geni_serial_power_off(uport);
+ }
+ IPC_LOG_MSG(msm_port->ipc_log_misc, "%s\n", __func__);
}
static int msm_geni_serial_port_setup(struct uart_port *uport)
{
int ret = 0;
struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+ unsigned long cfg0, cfg1;
- /* For now only assume FIFO mode. */
- msm_port->xfer_mode = FIFO_MODE;
+
set_rfr_wm(msm_port);
- ret = geni_se_init(uport->membase, msm_port->xfer_mode,
+ if (!uart_console(uport)) {
+ /* For now only assume FIFO mode. */
+ msm_port->xfer_mode = FIFO_MODE;
+ ret = geni_se_init(uport->membase, msm_port->xfer_mode,
msm_port->rx_wm, msm_port->rx_rfr);
- if (ret) {
- dev_err(uport->dev, "%s: Fail\n", __func__);
- goto exit_portsetup;
+ if (ret) {
+ dev_err(uport->dev, "%s: Fail\n", __func__);
+ goto exit_portsetup;
+ }
+ se_get_packing_config(8, 4, false, &cfg0, &cfg1);
+ geni_write_reg_nolog(cfg0, uport->membase,
+ SE_GENI_TX_PACKING_CFG0);
+ geni_write_reg_nolog(cfg1, uport->membase,
+ SE_GENI_TX_PACKING_CFG1);
}
-
msm_port->port_setup = true;
/*
* Ensure Port setup related IO completes before returning to
* framework.
*/
mb();
+ if (!uart_console(uport)) {
+ char name[30];
+
+ memset(name, 0, sizeof(name));
+ if (!msm_port->ipc_log_rx) {
+ scnprintf(name, sizeof(name), "%s%s",
+ dev_name(uport->dev), "_rx");
+ msm_port->ipc_log_rx = ipc_log_context_create(
+ IPC_LOG_TX_RX_PAGES, name, 0);
+ if (!msm_port->ipc_log_rx)
+ dev_info(uport->dev, "Err in Rx IPC Log\n");
+ }
+ memset(name, 0, sizeof(name));
+ if (!msm_port->ipc_log_tx) {
+ scnprintf(name, sizeof(name), "%s%s",
+ dev_name(uport->dev), "_tx");
+ msm_port->ipc_log_tx = ipc_log_context_create(
+ IPC_LOG_TX_RX_PAGES, name, 0);
+ if (!msm_port->ipc_log_tx)
+ dev_info(uport->dev, "Err in Tx IPC Log\n");
+ }
+ memset(name, 0, sizeof(name));
+ if (!msm_port->ipc_log_pwr) {
+ scnprintf(name, sizeof(name), "%s%s",
+ dev_name(uport->dev), "_pwr");
+ msm_port->ipc_log_pwr = ipc_log_context_create(
+ IPC_LOG_PWR_PAGES, name, 0);
+ if (!msm_port->ipc_log_pwr)
+ dev_info(uport->dev, "Err in Pwr IPC Log\n");
+ }
+ memset(name, 0, sizeof(name));
+ if (!msm_port->ipc_log_misc) {
+ scnprintf(name, sizeof(name), "%s%s",
+ dev_name(uport->dev), "_misc");
+ msm_port->ipc_log_misc = ipc_log_context_create(
+ IPC_LOG_MISC_PAGES, name, 0);
+ if (!msm_port->ipc_log_misc)
+ dev_info(uport->dev, "Err in Misc IPC Log\n");
+ }
+
+ }
exit_portsetup:
return ret;
}
@@ -802,12 +1121,36 @@
goto exit_startup;
}
+ if (msm_port->wakeup_irq > 0) {
+ ret = request_threaded_irq(msm_port->wakeup_irq, NULL,
+ msm_geni_wakeup_isr,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "hs_uart_wakeup", uport);
+ if (unlikely(ret)) {
+ dev_err(uport->dev, "%s:Failed to get WakeIRQ ret%d\n",
+ __func__, ret);
+ goto exit_startup;
+ }
+ disable_irq(msm_port->wakeup_irq);
+ }
+
if (likely(!uart_console(uport))) {
ret = msm_geni_serial_power_on(&msm_port->uport);
if (ret)
goto exit_startup;
}
+ if (unlikely(get_se_proto(uport->membase) != UART)) {
+ dev_err(uport->dev, "%s: Invalid FW %d loaded.\n",
+ __func__, get_se_proto(uport->membase));
+ if (unlikely(get_se_proto(uport->membase) != UART)) {
+ ret = -ENXIO;
+ disable_irq(uport->irq);
+ free_irq(uport->irq, msm_port);
+ goto exit_startup;
+ }
+ }
+
if (!msm_port->port_setup) {
if (msm_geni_serial_port_setup(uport))
goto exit_startup;
@@ -820,14 +1163,15 @@
* before returning to the framework.
*/
mb();
+ IPC_LOG_MSG(msm_port->ipc_log_misc, "%s\n", __func__);
exit_startup:
return ret;
}
-static int get_dfs_index(unsigned long clk_freq, unsigned long *ser_clk)
+static int get_clk_cfg(unsigned long clk_freq, unsigned long *ser_clk)
{
- unsigned long root_freq[] = {19200000, 7372800, 64000000,
- 96000000, 100000000, 102400000, 128000000};
+ unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
+ 32000000, 48000000, 64000000, 80000000, 96000000, 100000000};
int i;
int match = -1;
@@ -842,13 +1186,15 @@
}
if (match != -1)
*ser_clk = root_freq[match];
+ else
+ pr_err("clk_freq %ld\n", clk_freq);
return match;
}
static void geni_serial_write_term_regs(struct uart_port *uport, u32 loopback,
u32 tx_trans_cfg, u32 tx_parity_cfg, u32 rx_trans_cfg,
u32 rx_parity_cfg, u32 bits_per_char, u32 stop_bit_len,
- u32 rxstale, u32 s_clk_cfg)
+ u32 s_clk_cfg)
{
geni_write_reg_nolog(loopback, uport->membase, SE_UART_LOOPBACK_CFG);
geni_write_reg_nolog(tx_trans_cfg, uport->membase,
@@ -865,7 +1211,6 @@
SE_UART_RX_WORD_LEN);
geni_write_reg_nolog(stop_bit_len, uport->membase,
SE_UART_TX_STOP_BIT_LEN);
- geni_write_reg_nolog(rxstale, uport->membase, SE_UART_RX_STALE_CNT);
geni_write_reg_nolog(s_clk_cfg, uport->membase, GENI_SER_M_CLK_CFG);
geni_write_reg_nolog(s_clk_cfg, uport->membase, GENI_SER_S_CLK_CFG);
}
@@ -877,8 +1222,8 @@
int clk_div = 0;
*desired_clk_rate = baud * UART_OVERSAMPLING;
- dfs_index = get_dfs_index(*desired_clk_rate, &ser_clk);
- if (dfs_index < 1) {
+ dfs_index = get_clk_cfg(*desired_clk_rate, &ser_clk);
+ if (dfs_index < 0) {
pr_err("%s: Can't find matching DFS entry for baud %d\n",
__func__, baud);
clk_div = -EINVAL;
@@ -901,7 +1246,6 @@
unsigned int rx_trans_cfg;
unsigned int rx_parity_cfg;
unsigned int stop_bit_len;
- unsigned int rxstale;
unsigned int clk_div;
unsigned long ser_clk_cfg = 0;
struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
@@ -909,6 +1253,7 @@
/* baud rate */
baud = uart_get_baud_rate(uport, termios, old, 300, 4000000);
+ port->cur_baud = baud;
clk_div = get_clk_div_rate(baud, &clk_rate);
if (clk_div <= 0)
goto exit_set_termios;
@@ -966,8 +1311,6 @@
break;
}
- /* stale timer, set this to 16 characters. */
- rxstale = bits_per_char * STALE_TIMEOUT;
/* stop bits */
if (termios->c_cflag & CSTOPB)
@@ -984,19 +1327,26 @@
geni_serial_write_term_regs(uport, port->loopback, tx_trans_cfg,
tx_parity_cfg, rx_trans_cfg, rx_parity_cfg, bits_per_char,
- stop_bit_len, rxstale, ser_clk_cfg);
+ stop_bit_len, ser_clk_cfg);
+ IPC_LOG_MSG(port->ipc_log_misc, "%s: baud %d\n", __func__, baud);
+ IPC_LOG_MSG(port->ipc_log_misc, "Tx: trans_cfg%d parity %d\n",
+ tx_trans_cfg, tx_parity_cfg);
+ IPC_LOG_MSG(port->ipc_log_misc, "Rx: trans_cfg%d parity %d",
+ rx_trans_cfg, rx_parity_cfg);
+ IPC_LOG_MSG(port->ipc_log_misc, "BitsChar%d stop bit%d\n",
+ bits_per_char, stop_bit_len);
exit_set_termios:
return;
}
-static unsigned int msm_geni_serial_tx_empty(struct uart_port *port)
+static unsigned int msm_geni_serial_tx_empty(struct uart_port *uport)
{
unsigned int tx_fifo_status;
unsigned int is_tx_empty = 1;
- tx_fifo_status = geni_read_reg_nolog(port->membase,
- SE_GENI_TX_FIFO_STATUS);
+ tx_fifo_status = geni_read_reg_nolog(uport->membase,
+ SE_GENI_TX_FIFO_STATUS);
if (tx_fifo_status)
is_tx_empty = 0;
@@ -1013,11 +1363,12 @@
int parity = 'n';
int flow = 'n';
int ret = 0;
+ unsigned long cfg0, cfg1;
if (unlikely(co->index >= GENI_UART_NR_PORTS || co->index < 0))
return -ENXIO;
- dev_port = get_port_from_line(co->index);
+ dev_port = get_port_from_line(co->index, true);
if (IS_ERR_OR_NULL(dev_port)) {
ret = PTR_ERR(dev_port);
pr_err("Invalid line %d(%d)\n", co->index, ret);
@@ -1045,6 +1396,9 @@
* it else we could end up in data loss scenarios.
*/
msm_geni_serial_poll_cancel_tx(uport);
+ se_get_packing_config(8, 1, false, &cfg0, &cfg1);
+ geni_write_reg_nolog(cfg0, uport->membase, SE_GENI_TX_PACKING_CFG0);
+ geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_TX_PACKING_CFG1);
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -1066,7 +1420,6 @@
{
struct uart_port *uport = &dev->port;
int ret = 0;
- struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
u32 tx_trans_cfg = 0;
u32 tx_parity_cfg = 0;
u32 rx_trans_cfg = 0;
@@ -1078,6 +1431,7 @@
u32 baud = 115200;
u32 clk_div;
unsigned long clk_rate;
+ unsigned long cfg0, cfg1;
if (!uport->membase) {
ret = -ENOMEM;
@@ -1089,13 +1443,8 @@
goto exit_geni_serial_earlyconsetup;
}
- msm_port->xfer_mode = FIFO_MODE;
- set_rfr_wm(msm_port);
- msm_port->tx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
- msm_port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
- msm_port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
- geni_se_init(uport->membase, msm_port->xfer_mode, msm_port->rx_wm,
- msm_port->rx_rfr);
+ geni_se_init(uport->membase, FIFO_MODE, (DEF_FIFO_DEPTH_WORDS >> 1),
+ (DEF_FIFO_DEPTH_WORDS - 2));
/*
* Ignore Flow control.
* Disable Tx Parity.
@@ -1126,9 +1475,24 @@
* it else we could end up in data loss scenarios.
*/
msm_geni_serial_poll_cancel_tx(uport);
- geni_serial_write_term_regs(uport, 0, tx_trans_cfg,
- tx_parity_cfg, rx_trans_cfg, rx_parity_cfg, bits_per_char,
- stop_bit, rx_stale, s_clk_cfg);
+ se_get_packing_config(8, 1, false, &cfg0, &cfg1);
+ geni_write_reg_nolog(cfg0, uport->membase, SE_GENI_TX_PACKING_CFG0);
+ geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_TX_PACKING_CFG1);
+ geni_write_reg_nolog(tx_trans_cfg, uport->membase,
+ SE_UART_TX_TRANS_CFG);
+ geni_write_reg_nolog(tx_parity_cfg, uport->membase,
+ SE_UART_TX_PARITY_CFG);
+ geni_write_reg_nolog(rx_trans_cfg, uport->membase,
+ SE_UART_RX_TRANS_CFG);
+ geni_write_reg_nolog(rx_parity_cfg, uport->membase,
+ SE_UART_RX_PARITY_CFG);
+ geni_write_reg_nolog(bits_per_char, uport->membase,
+ SE_UART_TX_WORD_LEN);
+ geni_write_reg_nolog(bits_per_char, uport->membase,
+ SE_UART_RX_WORD_LEN);
+ geni_write_reg_nolog(stop_bit, uport->membase, SE_UART_TX_STOP_BIT_LEN);
+ geni_write_reg_nolog(s_clk_cfg, uport->membase, GENI_SER_M_CLK_CFG);
+ geni_write_reg_nolog(s_clk_cfg, uport->membase, GENI_SER_S_CLK_CFG);
dev->con->write = msm_geni_serial_early_console_write;
dev->con->setup = NULL;
@@ -1189,6 +1553,23 @@
dev_err(uport->dev, "Failed to create dbg dir\n");
}
+static const struct uart_ops msm_geni_console_pops = {
+ .tx_empty = msm_geni_serial_tx_empty,
+ .stop_tx = msm_geni_serial_stop_tx,
+ .start_tx = msm_geni_serial_start_tx,
+ .stop_rx = msm_geni_serial_stop_rx,
+ .set_termios = msm_geni_serial_set_termios,
+ .startup = msm_geni_serial_startup,
+ .config_port = msm_geni_serial_config_port,
+ .shutdown = msm_geni_serial_shutdown,
+ .type = msm_geni_serial_get_type,
+ .set_mctrl = msm_geni_cons_set_mctrl,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = msm_geni_serial_get_char,
+ .poll_put_char = msm_geni_serial_poll_put_char,
+#endif
+};
+
static const struct uart_ops msm_geni_serial_pops = {
.tx_empty = msm_geni_serial_tx_empty,
.stop_tx = msm_geni_serial_stop_tx,
@@ -1200,10 +1581,10 @@
.shutdown = msm_geni_serial_shutdown,
.type = msm_geni_serial_get_type,
.set_mctrl = msm_geni_serial_set_mctrl,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = msm_geni_serial_get_char,
- .poll_put_char = msm_geni_serial_poll_put_char,
-#endif
+ .get_mctrl = msm_geni_serial_get_mctrl,
+ .break_ctl = msm_geni_serial_break_ctl,
+ .flush_buffer = NULL,
+ .ioctl = msm_geni_serial_ioctl,
};
static const struct of_device_id msm_geni_device_tbl[] = {
@@ -1225,17 +1606,7 @@
struct resource *res;
struct uart_driver *drv;
const struct of_device_id *id;
-
- if (pdev->dev.of_node)
- line = of_alias_get_id(pdev->dev.of_node, "serial");
- else
- line = pdev->id;
-
- if (line < 0)
- line = atomic_inc_return(&uart_line_id) - 1;
-
- if ((line < 0) || (line >= GENI_UART_NR_PORTS))
- return -ENXIO;
+ bool is_console = false;
id = of_match_device(msm_geni_device_tbl, &pdev->dev);
if (id) {
@@ -1246,7 +1617,22 @@
return -ENODEV;
}
- dev_port = get_port_from_line(line);
+ if (pdev->dev.of_node) {
+ if (drv->cons)
+ line = of_alias_get_id(pdev->dev.of_node, "serial");
+ else
+ line = of_alias_get_id(pdev->dev.of_node, "hsuart");
+ } else {
+ line = pdev->id;
+ }
+
+ if (line < 0)
+ line = atomic_inc_return(&uart_line_id) - 1;
+
+ if ((line < 0) || (line >= GENI_UART_NR_PORTS))
+ return -ENXIO;
+ is_console = (drv->cons ? true : false);
+ dev_port = get_port_from_line(line, is_console);
if (IS_ERR_OR_NULL(dev_port)) {
ret = PTR_ERR(dev_port);
dev_err(&pdev->dev, "Invalid line %d(%d)\n",
@@ -1279,9 +1665,13 @@
dev_port->serial_rsc.ab = UART_CORE2X_VOTE;
dev_port->serial_rsc.ib = DEFAULT_SE_CLK * DEFAULT_BUS_WIDTH;
} else {
- dev_info(&pdev->dev, "No bus master specified");
+ dev_info(&pdev->dev, "No bus master specified\n");
}
+ if (of_property_read_u8(pdev->dev.of_node, "qcom,wakeup-byte",
+ &dev_port->wakeup_byte))
+ dev_info(&pdev->dev, "No Wakeup byte specified\n");
+
dev_port->serial_rsc.se_clk = devm_clk_get(&pdev->dev, "se-clk");
if (IS_ERR(dev_port->serial_rsc.se_clk)) {
ret = PTR_ERR(dev_port->serial_rsc.se_clk);
@@ -1342,6 +1732,7 @@
goto exit_geni_serial_probe;
}
+ wakeup_source_init(&dev_port->geni_wake, dev_name(&pdev->dev));
dev_port->tx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
dev_port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
dev_port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
@@ -1355,9 +1746,14 @@
goto exit_geni_serial_probe;
}
+ /* Optional to use the Rx pin as wakeup irq */
+ dev_port->wakeup_irq = platform_get_irq(pdev, 1);
+ if ((dev_port->wakeup_irq < 0 && !is_console))
+ dev_info(&pdev->dev, "No wakeup IRQ configured\n");
+
uport->private_data = (void *)drv;
platform_set_drvdata(pdev, dev_port);
- if (drv->cons) {
+ if (is_console) {
dev_port->handle_rx = handle_rx_console;
dev_port->rx_fifo = devm_kzalloc(uport->dev, sizeof(u32),
GFP_KERNEL);
@@ -1366,13 +1762,11 @@
dev_port->rx_fifo = devm_kzalloc(uport->dev,
sizeof(dev_port->rx_fifo_depth * sizeof(u32)),
GFP_KERNEL);
- pm_runtime_set_autosuspend_delay(&pdev->dev, MSEC_PER_SEC);
- pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_enable(&pdev->dev);
}
dev_info(&pdev->dev, "Serial port%d added.FifoSize %d is_console%d\n",
- line, uport->fifosize, (drv->cons ? 1 : 0));
+ line, uport->fifosize, is_console);
device_create_file(uport->dev, &dev_attr_loopback);
msm_geni_serial_debug_init(uport);
dev_port->port_setup = false;
@@ -1388,6 +1782,7 @@
struct uart_driver *drv =
(struct uart_driver *)port->uport.private_data;
+ wakeup_source_trash(&port->geni_wake);
uart_remove_one_port(drv, &port->uport);
msm_bus_scale_unregister(port->serial_rsc.bus_bw);
return 0;
@@ -1399,16 +1794,38 @@
{
struct platform_device *pdev = to_platform_device(dev);
struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
+ int ret = 0;
- return se_geni_resources_off(&port->serial_rsc);
+ ret = se_geni_resources_off(&port->serial_rsc);
+ if (ret) {
+ dev_err(dev, "%s: Error ret %d\n", __func__, ret);
+ goto exit_runtime_suspend;
+ }
+ if (port->wakeup_irq > 0)
+ enable_irq(port->wakeup_irq);
+ IPC_LOG_MSG(port->ipc_log_pwr, "%s: Current usage count %d\n", __func__,
+ atomic_read(&dev->power.usage_count));
+exit_runtime_suspend:
+ return ret;
}
static int msm_geni_serial_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
+ int ret = 0;
- return se_geni_resources_on(&port->serial_rsc);
+ if (port->wakeup_irq > 0)
+ disable_irq(port->wakeup_irq);
+ ret = se_geni_resources_on(&port->serial_rsc);
+ if (ret) {
+ dev_err(dev, "%s: Error ret %d\n", __func__, ret);
+ goto exit_runtime_resume;
+ }
+ IPC_LOG_MSG(port->ipc_log_pwr, "%s: Current usage count %d\n", __func__,
+ atomic_read(&dev->power.usage_count));
+exit_runtime_resume:
+ return ret;
}
static int msm_geni_serial_sys_suspend_noirq(struct device *dev)
@@ -1435,9 +1852,11 @@
struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
struct uart_port *uport = &port->uport;
- if (uart_console(uport))
+ if (uart_console(uport)) {
+ se_geni_resources_on(&port->serial_rsc);
uart_resume_port((struct uart_driver *)uport->private_data,
uport);
+ }
return 0;
}
#else
@@ -1504,6 +1923,13 @@
msm_geni_serial_ports[i].uport.line = i;
}
+ for (i = 0; i < GENI_UART_CONS_PORTS; i++) {
+ msm_geni_console_port.uport.iotype = UPIO_MEM;
+ msm_geni_console_port.uport.ops = &msm_geni_console_pops;
+ msm_geni_console_port.uport.flags = UPF_BOOT_AUTOCONF;
+ msm_geni_console_port.uport.line = i;
+ }
+
ret = console_register(&msm_geni_console_driver);
if (ret)
return ret;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 0dfe271..56df0f6 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -301,9 +301,6 @@
*/
if (dwc->ep0_bounced && dep->number <= 1) {
dwc->ep0_bounced = false;
-
- usb_gadget_unmap_request_by_dev(dwc->sysdev,
- &req->request, req->direction);
unmap_after_complete = true;
} else {
usb_gadget_unmap_request(&dwc->gadget,
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 12f2252..953275b 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -2080,11 +2080,6 @@
if (inode_dirty_flags)
__mark_inode_dirty(inode, inode_dirty_flags);
- if (ia_valid & ATTR_MODE) {
- err = posix_acl_chmod(inode, attr->ia_mode);
- if (err)
- goto out_put;
- }
if (mask) {
req->r_inode = inode;
@@ -2098,13 +2093,11 @@
ceph_cap_string(dirtied), mask);
ceph_mdsc_put_request(req);
- if (mask & CEPH_SETATTR_SIZE)
+ ceph_free_cap_flush(prealloc_cf);
+
+ if (err >= 0 && (mask & CEPH_SETATTR_SIZE))
__ceph_do_pending_vmtruncate(inode);
- ceph_free_cap_flush(prealloc_cf);
- return err;
-out_put:
- ceph_mdsc_put_request(req);
- ceph_free_cap_flush(prealloc_cf);
+
return err;
}
@@ -2123,7 +2116,12 @@
if (err != 0)
return err;
- return __ceph_setattr(inode, attr);
+ err = __ceph_setattr(inode, attr);
+
+ if (err >= 0 && (attr->ia_valid & ATTR_MODE))
+ err = posix_acl_chmod(inode, attr->ia_mode);
+
+ return err;
}
/*
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index dba2ff8..4523346 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -358,6 +358,8 @@
{
unsigned int len, v, hdr, dlen;
u32 max_blocksize = svc_max_payload(rqstp);
+ struct kvec *head = rqstp->rq_arg.head;
+ struct kvec *tail = rqstp->rq_arg.tail;
p = decode_fh(p, &args->fh);
if (!p)
@@ -367,6 +369,8 @@
args->count = ntohl(*p++);
args->stable = ntohl(*p++);
len = args->len = ntohl(*p++);
+ if ((void *)p > head->iov_base + head->iov_len)
+ return 0;
/*
* The count must equal the amount of data passed.
*/
@@ -377,9 +381,8 @@
* Check to make sure that we got the right number of
* bytes.
*/
- hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
- dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
- + rqstp->rq_arg.tail[0].iov_len - hdr;
+ hdr = (void*)p - head->iov_base;
+ dlen = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len - hdr;
/*
* Round the length of the data which was specified up to
* the next multiple of XDR units and then compare that
@@ -396,7 +399,7 @@
len = args->len = max_blocksize;
}
rqstp->rq_vec[0].iov_base = (void*)p;
- rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
+ rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
v = 0;
while (len > rqstp->rq_vec[v].iov_len) {
len -= rqstp->rq_vec[v].iov_len;
@@ -471,6 +474,8 @@
/* first copy and check from the first page */
old = (char*)p;
vec = &rqstp->rq_arg.head[0];
+ if ((void *)old > vec->iov_base + vec->iov_len)
+ return 0;
avail = vec->iov_len - (old - (char*)vec->iov_base);
while (len && avail && *old) {
*new++ = *old++;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index a2b65fc..1645b97 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -733,6 +733,37 @@
return nfserr;
}
+/*
+ * A write procedure can have a large argument, and a read procedure can
+ * have a large reply, but no NFSv2 or NFSv3 procedure has argument and
+ * reply that can both be larger than a page. The xdr code has taken
+ * advantage of this assumption to be a sloppy about bounds checking in
+ * some cases. Pending a rewrite of the NFSv2/v3 xdr code to fix that
+ * problem, we enforce these assumptions here:
+ */
+static bool nfs_request_too_big(struct svc_rqst *rqstp,
+ struct svc_procedure *proc)
+{
+ /*
+ * The ACL code has more careful bounds-checking and is not
+ * susceptible to this problem:
+ */
+ if (rqstp->rq_prog != NFS_PROGRAM)
+ return false;
+ /*
+ * Ditto NFSv4 (which can in theory have argument and reply both
+ * more than a page):
+ */
+ if (rqstp->rq_vers >= 4)
+ return false;
+ /* The reply will be small, we're OK: */
+ if (proc->pc_xdrressize > 0 &&
+ proc->pc_xdrressize < XDR_QUADLEN(PAGE_SIZE))
+ return false;
+
+ return rqstp->rq_arg.len > PAGE_SIZE;
+}
+
int
nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
{
@@ -745,6 +776,11 @@
rqstp->rq_vers, rqstp->rq_proc);
proc = rqstp->rq_procinfo;
+ if (nfs_request_too_big(rqstp, proc)) {
+ dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
+ *statp = rpc_garbage_args;
+ return 1;
+ }
/*
* Give the xdr decoder a chance to change this if it wants
* (necessary in the NFSv4.0 compound case)
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 41b468a..de07ff6 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -280,6 +280,7 @@
struct nfsd_writeargs *args)
{
unsigned int len, hdr, dlen;
+ struct kvec *head = rqstp->rq_arg.head;
int v;
p = decode_fh(p, &args->fh);
@@ -300,9 +301,10 @@
* Check to make sure that we got the right number of
* bytes.
*/
- hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
- dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
- - hdr;
+ hdr = (void*)p - head->iov_base;
+ if (hdr > head->iov_len)
+ return 0;
+ dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
/*
* Round the length of the data which was specified up to
@@ -316,7 +318,7 @@
return 0;
rqstp->rq_vec[0].iov_base = (void*)p;
- rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
+ rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
v = 0;
while (len > rqstp->rq_vec[v].iov_len) {
len -= rqstp->rq_vec[v].iov_len;
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index bda14ef..744ea4f 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -125,6 +125,7 @@
* BVEC_POOL_IDX()
*/
#define BIO_RESET_BITS 10
+#define BIO_INLINECRYPT 15
/*
* We support 6 different bvec pools, the last one is magic in that it
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 1f6892c..e3d181e 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -436,6 +436,7 @@
void iommu_fwspec_free(struct device *dev);
int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
int iommu_fwspec_get_id(struct device *dev, u32 *id);
+int iommu_is_available(struct device *dev);
#else /* CONFIG_IOMMU_API */
@@ -711,6 +712,10 @@
return -ENODEV;
}
+static inline int iommu_is_available(struct device *dev)
+{
+ return -ENODEV;
+}
#endif /* CONFIG_IOMMU_API */
#endif /* __LINUX_IOMMU_H */
diff --git a/include/linux/msm_pcie.h b/include/linux/msm_pcie.h
index 8316aaa..b9527d3 100644
--- a/include/linux/msm_pcie.h
+++ b/include/linux/msm_pcie.h
@@ -157,18 +157,6 @@
int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base,
u32 offset, u32 mask, u32 value);
-/*
- * msm_pcie_configure_sid - calculates the SID for a PCIe endpoint.
- * @dev: device structure
- * @sid: the calculated SID
- * @domain: the domain number of the Root Complex
- *
- * This function calculates the SID for a PCIe endpoint device.
- *
- * Return: 0 on success, negative value on error
- */
-int msm_pcie_configure_sid(struct device *dev, u32 *sid,
- int *domain);
#else /* !CONFIG_PCI_MSM */
static inline int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr,
void *user, void *data, u32 options)
@@ -206,12 +194,6 @@
{
return -ENODEV;
}
-
-static inline int msm_pcie_configure_sid(struct device *dev, u32 *sid,
- int *domain)
-{
- return -ENODEV;
-}
#endif /* CONFIG_PCI_MSM */
#endif /* __MSM_PCIE_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index e25f183..bd22670 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -806,6 +806,7 @@
void phy_mac_interrupt(struct phy_device *phydev, int new_link);
void phy_start_machine(struct phy_device *phydev);
void phy_stop_machine(struct phy_device *phydev);
+void phy_trigger_machine(struct phy_device *phydev, bool sync);
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
int phy_ethtool_ksettings_get(struct phy_device *phydev,
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index cb4387d..12b3d51e8 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -86,6 +86,7 @@
#define SE_GENI_TX_WATERMARK_REG (0x80C)
#define SE_GENI_RX_WATERMARK_REG (0x810)
#define SE_GENI_RX_RFR_WATERMARK_REG (0x814)
+#define SE_GENI_IOS (0x908)
#define SE_GENI_M_GP_LENGTH (0x910)
#define SE_GENI_S_GP_LENGTH (0x914)
#define SE_GSI_EVENT_EN (0xE18)
@@ -228,6 +229,10 @@
#define GENI_M_EVENT_EN (BIT(2))
#define GENI_S_EVENT_EN (BIT(3))
+/* SE_GENI_IOS fields */
+#define IO2_DATA_IN (BIT(1))
+#define RX_DATA_IN (BIT(0))
+
/* SE_IRQ_EN fields */
#define DMA_RX_IRQ_EN (BIT(0))
#define DMA_TX_IRQ_EN (BIT(1))
@@ -275,7 +280,7 @@
static inline void geni_write_reg(unsigned int value, void __iomem *base,
int offset)
{
- return writel_relaxed(value, (base + offset));
+ writel_relaxed(value, (base + offset));
}
static inline int get_se_proto(void __iomem *base)
@@ -479,11 +484,11 @@
return rx_fifo_depth;
}
-static inline void se_config_packing(void __iomem *base, int bpw,
- int pack_words, bool msb_to_lsb)
+static inline void se_get_packing_config(int bpw, int pack_words,
+ bool msb_to_lsb, unsigned long *cfg0,
+ unsigned long *cfg1)
{
u32 cfg[4] = {0};
- unsigned long cfg0, cfg1;
int len = ((bpw < 8) ? (bpw - 1) : 7);
int idx = ((msb_to_lsb == 1) ? len : 0);
int iter = (bpw * pack_words) >> 3;
@@ -495,8 +500,16 @@
if (i == iter - 1)
cfg[i] |= 1;
}
- cfg0 = cfg[0] | (cfg[1] << 10);
- cfg1 = cfg[2] | (cfg[3] << 10);
+ *cfg0 = cfg[0] | (cfg[1] << 10);
+ *cfg1 = cfg[2] | (cfg[3] << 10);
+}
+
+static inline void se_config_packing(void __iomem *base, int bpw,
+ int pack_words, bool msb_to_lsb)
+{
+ unsigned long cfg0, cfg1;
+
+ se_get_packing_config(bpw, pack_words, msb_to_lsb, &cfg0, &cfg1);
geni_write_reg(cfg0, base, SE_GENI_TX_PACKING_CFG0);
geni_write_reg(cfg1, base, SE_GENI_TX_PACKING_CFG1);
geni_write_reg(cfg0, base, SE_GENI_RX_PACKING_CFG0);
diff --git a/include/linux/sde_rsc.h b/include/linux/sde_rsc.h
index 60cc768..f3fa9e6 100644
--- a/include/linux/sde_rsc.h
+++ b/include/linux/sde_rsc.h
@@ -79,6 +79,7 @@
* @current_state: current client state
* @crtc_id: crtc_id associated with this rsc client.
* @rsc_index: rsc index of a client - only index "0" valid.
+ * @id: Index of client. It will be assigned during client_create call
* @list: list to attach client master list
*/
struct sde_rsc_client {
@@ -86,6 +87,7 @@
short current_state;
int crtc_id;
u32 rsc_index;
+ u32 id;
struct list_head list;
};
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index 262fa64..0583431 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -103,6 +103,7 @@
int msm_vidc_g_fmt(void *instance, struct v4l2_format *f);
int msm_vidc_s_ctrl(void *instance, struct v4l2_control *a);
int msm_vidc_s_ext_ctrl(void *instance, struct v4l2_ext_controls *a);
+int msm_vidc_g_ext_ctrl(void *instance, struct v4l2_ext_controls *a);
int msm_vidc_g_ctrl(void *instance, struct v4l2_control *a);
int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b);
int msm_vidc_release_buffer(void *instance, int buffer_type,
diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h
index 34434fd..75e6ccd 100644
--- a/include/soc/qcom/rpmh.h
+++ b/include/soc/qcom/rpmh.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,8 @@
int rpmh_write_passthru(struct rpmh_client *rc, enum rpmh_state state,
struct tcs_cmd *cmd, int *n);
+int rpmh_mode_solver_set(struct rpmh_client *rc, bool enable);
+
int rpmh_write_control(struct rpmh_client *rc, struct tcs_cmd *cmd, int n);
int rpmh_invalidate(struct rpmh_client *rc);
@@ -70,6 +72,9 @@
enum rpmh_state state, struct tcs_cmd *cmd, int *n)
{ return -ENODEV; }
+static inline int rpmh_mode_solver_set(struct rpmh_client *rc, bool enable)
+{ return -ENODEV; }
+
static inline int rpmh_write_control(struct rpmh_client *rc,
struct tcs_cmd *cmd, int n)
{ return -ENODEV; }
diff --git a/include/uapi/asm-generic/ioctls.h b/include/uapi/asm-generic/ioctls.h
index 143dacb..deb98c7 100644
--- a/include/uapi/asm-generic/ioctls.h
+++ b/include/uapi/asm-generic/ioctls.h
@@ -77,6 +77,9 @@
#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
+#define TIOCPMGET 0x5441 /* PM get */
+#define TIOCPMPUT 0x5442 /* PM put */
+#define TIOCPMACT 0x5443 /* PM is active */
#define FIONCLEX 0x5450
#define FIOCLEX 0x5451
diff --git a/include/uapi/linux/ipv6_route.h b/include/uapi/linux/ipv6_route.h
index f6598d1..316e838 100644
--- a/include/uapi/linux/ipv6_route.h
+++ b/include/uapi/linux/ipv6_route.h
@@ -34,7 +34,7 @@
#define RTF_PREF(pref) ((pref) << 27)
#define RTF_PREF_MASK 0x18000000
-#define RTF_PCPU 0x40000000
+#define RTF_PCPU 0x40000000 /* read-only: can not be set by user */
#define RTF_LOCAL 0x80000000
diff --git a/include/uapi/media/Kbuild b/include/uapi/media/Kbuild
index 5f375c4..478f7fe 100644
--- a/include/uapi/media/Kbuild
+++ b/include/uapi/media/Kbuild
@@ -1,3 +1,4 @@
+header-y += cam_cpas.h
header-y += cam_defs.h
header-y += cam_isp.h
header-y += cam_isp_vfe.h
diff --git a/include/uapi/media/cam_cpas.h b/include/uapi/media/cam_cpas.h
new file mode 100644
index 0000000..300bd87
--- /dev/null
+++ b/include/uapi/media/cam_cpas.h
@@ -0,0 +1,23 @@
+#ifndef __UAPI_CAM_CPAS_H__
+#define __UAPI_CAM_CPAS_H__
+
+#include "cam_defs.h"
+
+#define CAM_FAMILY_CAMERA_SS 1
+#define CAM_FAMILY_CPAS_SS 2
+
+/**
+ * struct cam_cpas_query_cap - CPAS query device capability payload
+ *
+ * @camera_family : Camera family type
+ * @reserved : Reserved field for alignment
+ * @camera_version : Camera version
+ *
+ */
+struct cam_cpas_query_cap {
+ uint32_t camera_family;
+ uint32_t reserved;
+ struct cam_hw_version camera_version;
+};
+
+#endif /* __UAPI_CAM_CPAS_H__ */
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 85d1c94..7c9f94c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1829,14 +1829,15 @@
for (i = 0; i < MAX_BPF_REG; i++)
if (regs[i].type == PTR_TO_PACKET && regs[i].id == dst_reg->id)
- regs[i].range = dst_reg->off;
+ /* keep the maximum range already checked */
+ regs[i].range = max(regs[i].range, dst_reg->off);
for (i = 0; i < MAX_BPF_STACK; i += BPF_REG_SIZE) {
if (state->stack_slot_type[i] != STACK_SPILL)
continue;
reg = &state->spilled_regs[i / BPF_REG_SIZE];
if (reg->type == PTR_TO_PACKET && reg->id == dst_reg->id)
- reg->range = dst_reg->off;
+ reg->range = max(reg->range, dst_reg->off);
}
}
diff --git a/net/9p/client.c b/net/9p/client.c
index 3fc94a4..cf129fe 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -2101,6 +2101,10 @@
trace_9p_protocol_dump(clnt, req->rc);
goto free_and_error;
}
+ if (rsize < count) {
+ pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize);
+ count = rsize;
+ }
p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 9901e5b..f45f619 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -859,7 +859,8 @@
if (skb)
skb = skb_clone(skb, GFP_ATOMIC);
write_unlock(&neigh->lock);
- neigh->ops->solicit(neigh, skb);
+ if (neigh->ops->solicit)
+ neigh->ops->solicit(neigh, skb);
atomic_inc(&neigh->probes);
kfree_skb(skb);
}
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 53599bd..457f882 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -105,15 +105,21 @@
while ((skb = skb_dequeue(&npinfo->txq))) {
struct net_device *dev = skb->dev;
struct netdev_queue *txq;
+ unsigned int q_index;
if (!netif_device_present(dev) || !netif_running(dev)) {
kfree_skb(skb);
continue;
}
- txq = skb_get_tx_queue(dev, skb);
-
local_irq_save(flags);
+ /* check if skb->queue_mapping is still valid */
+ q_index = skb_get_queue_mapping(skb);
+ if (unlikely(q_index >= dev->real_num_tx_queues)) {
+ q_index = q_index % dev->real_num_tx_queues;
+ skb_set_queue_mapping(skb, q_index);
+ }
+ txq = netdev_get_tx_queue(dev, q_index);
HARD_TX_LOCK(dev, txq, smp_processor_id());
if (netif_xmit_frozen_or_stopped(txq) ||
netpoll_start_xmit(skb, dev, txq) != NETDEV_TX_OK) {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 8de6707..ba1146c 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3082,22 +3082,32 @@
if (sg && csum && (mss != GSO_BY_FRAGS)) {
if (!(features & NETIF_F_GSO_PARTIAL)) {
struct sk_buff *iter;
+ unsigned int frag_len;
if (!list_skb ||
!net_gso_ok(features, skb_shinfo(head_skb)->gso_type))
goto normal;
- /* Split the buffer at the frag_list pointer.
- * This is based on the assumption that all
- * buffers in the chain excluding the last
- * containing the same amount of data.
+ /* If we get here then all the required
+ * GSO features except frag_list are supported.
+ * Try to split the SKB to multiple GSO SKBs
+ * with no frag_list.
+ * Currently we can do that only when the buffers don't
+ * have a linear part and all the buffers except
+ * the last are of the same length.
*/
+ frag_len = list_skb->len;
skb_walk_frags(head_skb, iter) {
+ if (frag_len != iter->len && iter->next)
+ goto normal;
if (skb_headlen(iter))
goto normal;
len -= iter->len;
}
+
+ if (len != frag_len)
+ goto normal;
}
/* GSO partial only requires that we trim off any excess that
@@ -3785,6 +3795,7 @@
serr->ee.ee_errno = ENOMSG;
serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
serr->ee.ee_info = tstype;
+ serr->header.h4.iif = skb->dev ? skb->dev->ifindex : 0;
if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) {
serr->ee.ee_data = skb_shinfo(skb)->tskey;
if (sk->sk_protocol == IPPROTO_TCP &&
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 9826695..4d37bdc 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -474,16 +474,15 @@
return false;
/* Support IP_PKTINFO on tstamp packets if requested, to correlate
- * timestamp with egress dev. Not possible for packets without dev
+ * timestamp with egress dev. Not possible for packets without iif
* or without payload (SOF_TIMESTAMPING_OPT_TSONLY).
*/
- if ((!(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_CMSG)) ||
- (!skb->dev))
+ info = PKTINFO_SKB_CB(skb);
+ if (!(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_CMSG) ||
+ !info->ipi_ifindex)
return false;
- info = PKTINFO_SKB_CB(skb);
info->ipi_spec_dst.s_addr = ip_hdr(skb)->saddr;
- info->ipi_ifindex = skb->dev->ifindex;
return true;
}
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 06879e6..93bfadf 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -156,17 +156,18 @@
void ping_unhash(struct sock *sk)
{
struct inet_sock *isk = inet_sk(sk);
+
pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num);
+ write_lock_bh(&ping_table.lock);
if (sk_hashed(sk)) {
- write_lock_bh(&ping_table.lock);
hlist_nulls_del(&sk->sk_nulls_node);
sk_nulls_node_init(&sk->sk_nulls_node);
sock_put(sk);
isk->inet_num = 0;
isk->inet_sport = 0;
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
- write_unlock_bh(&ping_table.lock);
}
+ write_unlock_bh(&ping_table.lock);
}
EXPORT_SYMBOL_GPL(ping_unhash);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index e6acef5..70c40ba2 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2581,7 +2581,7 @@
skb_reset_network_header(skb);
/* Bugfix: need to give ip_route_input enough of an IP header to not gag. */
- ip_hdr(skb)->protocol = IPPROTO_ICMP;
+ ip_hdr(skb)->protocol = IPPROTO_UDP;
skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
src = tb[RTA_SRC] ? nla_get_in_addr(tb[RTA_SRC]) : 0;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 6a90a0e..eb142ca 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2297,6 +2297,7 @@
tcp_init_send_head(sk);
memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
__sk_dst_reset(sk);
+ tcp_saved_syn_free(tp);
WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index f9038d6b..baea5df 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -167,12 +167,8 @@
}
out:
rcu_read_unlock();
+ memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
- /* Clear out private data before diag gets it and
- * the ca has not been initialized.
- */
- if (ca->get_info)
- memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
if (ca->flags & TCP_CONG_NEEDS_ECN)
INET_ECN_xmit(sk);
else
@@ -199,11 +195,10 @@
tcp_cleanup_congestion_control(sk);
icsk->icsk_ca_ops = ca;
icsk->icsk_ca_setsockopt = 1;
+ memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
- if (sk->sk_state != TCP_CLOSE) {
- memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
+ if (sk->sk_state != TCP_CLOSE)
tcp_init_congestion_control(sk);
- }
}
/* Manage refcounts on socket close. */
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 7588fa9..553138d 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3293,14 +3293,24 @@
static int fixup_permanent_addr(struct inet6_dev *idev,
struct inet6_ifaddr *ifp)
{
- if (!ifp->rt) {
- struct rt6_info *rt;
+ /* rt6i_ref == 0 means the host route was removed from the
+ * FIB, for example, if 'lo' device is taken down. In that
+ * case regenerate the host route.
+ */
+ if (!ifp->rt || !atomic_read(&ifp->rt->rt6i_ref)) {
+ struct rt6_info *rt, *prev;
rt = addrconf_dst_alloc(idev, &ifp->addr, false);
if (unlikely(IS_ERR(rt)))
return PTR_ERR(rt);
+ /* ifp->rt can be accessed outside of rtnl */
+ spin_lock(&ifp->lock);
+ prev = ifp->rt;
ifp->rt = rt;
+ spin_unlock(&ifp->lock);
+
+ ip6_rt_put(prev);
}
if (!(ifp->flags & IFA_F_NOPREFIXROUTE)) {
@@ -3642,14 +3652,19 @@
INIT_LIST_HEAD(&del_list);
list_for_each_entry_safe(ifa, tmp, &idev->addr_list, if_list) {
struct rt6_info *rt = NULL;
+ bool keep;
addrconf_del_dad_work(ifa);
+ keep = keep_addr && (ifa->flags & IFA_F_PERMANENT) &&
+ !addr_is_local(&ifa->addr);
+ if (!keep)
+ list_move(&ifa->if_list, &del_list);
+
write_unlock_bh(&idev->lock);
spin_lock_bh(&ifa->lock);
- if (keep_addr && (ifa->flags & IFA_F_PERMANENT) &&
- !addr_is_local(&ifa->addr)) {
+ if (keep) {
/* set state to skip the notifier below */
state = INET6_IFADDR_STATE_DEAD;
ifa->state = 0;
@@ -3661,8 +3676,6 @@
} else {
state = ifa->state;
ifa->state = INET6_IFADDR_STATE_DEAD;
-
- list_move(&ifa->if_list, &del_list);
}
spin_unlock_bh(&ifa->lock);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 1529833..a381772 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -401,9 +401,6 @@
* At one point, excluding local errors was a quick test to identify icmp/icmp6
* errors. This is no longer true, but the test remained, so the v6 stack,
* unlike v4, also honors cmsg requests on all wifi and timestamp errors.
- *
- * Timestamp code paths do not initialize the fields expected by cmsg:
- * the PKTINFO fields in skb->cb[]. Fill those in here.
*/
static bool ip6_datagram_support_cmsg(struct sk_buff *skb,
struct sock_exterr_skb *serr)
@@ -415,14 +412,9 @@
if (serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL)
return false;
- if (!skb->dev)
+ if (!IP6CB(skb)->iif)
return false;
- if (skb->protocol == htons(ETH_P_IPV6))
- IP6CB(skb)->iif = skb->dev->ifindex;
- else
- PKTINFO_SKB_CB(skb)->ipi_ifindex = skb->dev->ifindex;
-
return true;
}
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 885b411..97e89a2 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1037,7 +1037,7 @@
struct ip6_tnl *t = netdev_priv(dev);
struct net *net = t->net;
struct net_device_stats *stats = &t->dev->stats;
- struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ struct ipv6hdr *ipv6h;
struct ipv6_tel_txoption opt;
struct dst_entry *dst = NULL, *ndst = NULL;
struct net_device *tdev;
@@ -1057,26 +1057,28 @@
/* NBMA tunnel */
if (ipv6_addr_any(&t->parms.raddr)) {
- struct in6_addr *addr6;
- struct neighbour *neigh;
- int addr_type;
+ if (skb->protocol == htons(ETH_P_IPV6)) {
+ struct in6_addr *addr6;
+ struct neighbour *neigh;
+ int addr_type;
- if (!skb_dst(skb))
- goto tx_err_link_failure;
+ if (!skb_dst(skb))
+ goto tx_err_link_failure;
- neigh = dst_neigh_lookup(skb_dst(skb),
- &ipv6_hdr(skb)->daddr);
- if (!neigh)
- goto tx_err_link_failure;
+ neigh = dst_neigh_lookup(skb_dst(skb),
+ &ipv6_hdr(skb)->daddr);
+ if (!neigh)
+ goto tx_err_link_failure;
- addr6 = (struct in6_addr *)&neigh->primary_key;
- addr_type = ipv6_addr_type(addr6);
+ addr6 = (struct in6_addr *)&neigh->primary_key;
+ addr_type = ipv6_addr_type(addr6);
- if (addr_type == IPV6_ADDR_ANY)
- addr6 = &ipv6_hdr(skb)->daddr;
+ if (addr_type == IPV6_ADDR_ANY)
+ addr6 = &ipv6_hdr(skb)->daddr;
- memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
- neigh_release(neigh);
+ memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
+ neigh_release(neigh);
+ }
} else if (!(t->parms.flags &
(IP6_TNL_F_USE_ORIG_TCLASS | IP6_TNL_F_USE_ORIG_FWMARK))) {
/* enable the cache only only if the routing decision does
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 7f4265b..117405d 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -774,7 +774,8 @@
* Delete a VIF entry
*/
-static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head)
+static int mif6_delete(struct mr6_table *mrt, int vifi, int notify,
+ struct list_head *head)
{
struct mif_device *v;
struct net_device *dev;
@@ -820,7 +821,7 @@
dev->ifindex, &in6_dev->cnf);
}
- if (v->flags & MIFF_REGISTER)
+ if ((v->flags & MIFF_REGISTER) && !notify)
unregister_netdevice_queue(dev, head);
dev_put(dev);
@@ -1331,7 +1332,6 @@
struct mr6_table *mrt;
struct mif_device *v;
int ct;
- LIST_HEAD(list);
if (event != NETDEV_UNREGISTER)
return NOTIFY_DONE;
@@ -1340,10 +1340,9 @@
v = &mrt->vif6_table[0];
for (ct = 0; ct < mrt->maxvif; ct++, v++) {
if (v->dev == dev)
- mif6_delete(mrt, ct, &list);
+ mif6_delete(mrt, ct, 1, NULL);
}
}
- unregister_netdevice_many(&list);
return NOTIFY_DONE;
}
@@ -1552,7 +1551,7 @@
for (i = 0; i < mrt->maxvif; i++) {
if (!all && (mrt->vif6_table[i].flags & VIFF_STATIC))
continue;
- mif6_delete(mrt, i, &list);
+ mif6_delete(mrt, i, 0, &list);
}
unregister_netdevice_many(&list);
@@ -1706,7 +1705,7 @@
if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
return -EFAULT;
rtnl_lock();
- ret = mif6_delete(mrt, mifi, NULL);
+ ret = mif6_delete(mrt, mifi, 0, NULL);
rtnl_unlock();
return ret;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 5665375..1a34da0 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -1172,8 +1172,7 @@
spin_lock_bh(&sk->sk_receive_queue.lock);
skb = skb_peek(&sk->sk_receive_queue);
if (skb)
- amount = skb_tail_pointer(skb) -
- skb_transport_header(skb);
+ amount = skb->len;
spin_unlock_bh(&sk->sk_receive_queue.lock);
return put_user(amount, (int __user *)arg);
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 73527d8..7d17670 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1825,6 +1825,10 @@
int addr_type;
int err = -EINVAL;
+ /* RTF_PCPU is an internal flag; can not be set by userspace */
+ if (cfg->fc_flags & RTF_PCPU)
+ goto out;
+
if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128)
goto out;
#ifndef CONFIG_IPV6_SUBTREES
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index a646f34..fecad10 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -1685,7 +1685,7 @@
struct kcm_attach info;
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
- err = -EFAULT;
+ return -EFAULT;
err = kcm_attach_ioctl(sock, &info);
@@ -1695,7 +1695,7 @@
struct kcm_unattach info;
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
- err = -EFAULT;
+ return -EFAULT;
err = kcm_unattach_ioctl(sock, &info);
@@ -1706,7 +1706,7 @@
struct socket *newsock = NULL;
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
- err = -EFAULT;
+ return -EFAULT;
err = kcm_clone(sock, &info, &newsock);
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index a2ed3bd..e702cb95 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -278,7 +278,8 @@
}
EXPORT_SYMBOL_GPL(l2tp_session_find);
-struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth)
+struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
+ bool do_ref)
{
int hash;
struct l2tp_session *session;
@@ -288,6 +289,9 @@
for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
hlist_for_each_entry(session, &tunnel->session_hlist[hash], hlist) {
if (++count > nth) {
+ l2tp_session_inc_refcount(session);
+ if (do_ref && session->ref)
+ session->ref(session);
read_unlock_bh(&tunnel->hlist_lock);
return session;
}
@@ -298,7 +302,7 @@
return NULL;
}
-EXPORT_SYMBOL_GPL(l2tp_session_find_nth);
+EXPORT_SYMBOL_GPL(l2tp_session_get_nth);
/* Lookup a session by interface name.
* This is very inefficient but is only used by management interfaces.
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 181e755c..e7233ba 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -243,7 +243,8 @@
struct l2tp_session *l2tp_session_find(struct net *net,
struct l2tp_tunnel *tunnel,
u32 session_id);
-struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth);
+struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
+ bool do_ref);
struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname);
struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id);
struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth);
diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c
index 2d6760a..d100aed 100644
--- a/net/l2tp/l2tp_debugfs.c
+++ b/net/l2tp/l2tp_debugfs.c
@@ -53,7 +53,7 @@
static void l2tp_dfs_next_session(struct l2tp_dfs_seq_data *pd)
{
- pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx);
+ pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true);
pd->session_idx++;
if (pd->session == NULL) {
@@ -238,10 +238,14 @@
}
/* Show the tunnel or session context */
- if (pd->session == NULL)
+ if (!pd->session) {
l2tp_dfs_seq_tunnel_show(m, pd->tunnel);
- else
+ } else {
l2tp_dfs_seq_session_show(m, pd->session);
+ if (pd->session->deref)
+ pd->session->deref(pd->session);
+ l2tp_session_dec_refcount(pd->session);
+ }
out:
return 0;
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index ff750bb..2066953 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -178,9 +178,10 @@
tunnel_id = ntohl(*(__be32 *) &skb->data[4]);
tunnel = l2tp_tunnel_find(net, tunnel_id);
- if (tunnel != NULL)
+ if (tunnel) {
sk = tunnel->sock;
- else {
+ sock_hold(sk);
+ } else {
struct iphdr *iph = (struct iphdr *) skb_network_header(skb);
read_lock_bh(&l2tp_ip_lock);
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 7095786..26cf4dc 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -191,9 +191,10 @@
tunnel_id = ntohl(*(__be32 *) &skb->data[4]);
tunnel = l2tp_tunnel_find(net, tunnel_id);
- if (tunnel != NULL)
+ if (tunnel) {
sk = tunnel->sock;
- else {
+ sock_hold(sk);
+ } else {
struct ipv6hdr *iph = ipv6_hdr(skb);
read_lock_bh(&l2tp_ip6_lock);
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index bf31177..9f66272 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -844,7 +844,7 @@
goto out;
}
- session = l2tp_session_find_nth(tunnel, si);
+ session = l2tp_session_get_nth(tunnel, si, false);
if (session == NULL) {
ti++;
tunnel = NULL;
@@ -854,8 +854,11 @@
if (l2tp_nl_session_send(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- session, L2TP_CMD_SESSION_GET) < 0)
+ session, L2TP_CMD_SESSION_GET) < 0) {
+ l2tp_session_dec_refcount(session);
break;
+ }
+ l2tp_session_dec_refcount(session);
si++;
}
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 41d47bf..1387f54 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -450,6 +450,10 @@
static void pppol2tp_session_destruct(struct sock *sk)
{
struct l2tp_session *session = sk->sk_user_data;
+
+ skb_queue_purge(&sk->sk_receive_queue);
+ skb_queue_purge(&sk->sk_write_queue);
+
if (session) {
sk->sk_user_data = NULL;
BUG_ON(session->magic != L2TP_SESSION_MAGIC);
@@ -488,9 +492,6 @@
l2tp_session_queue_purge(session);
sock_put(sk);
}
- skb_queue_purge(&sk->sk_receive_queue);
- skb_queue_purge(&sk->sk_write_queue);
-
release_sock(sk);
/* This will delete the session context via
@@ -1554,7 +1555,7 @@
static void pppol2tp_next_session(struct net *net, struct pppol2tp_seq_data *pd)
{
- pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx);
+ pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true);
pd->session_idx++;
if (pd->session == NULL) {
@@ -1681,10 +1682,14 @@
/* Show the tunnel or session context.
*/
- if (pd->session == NULL)
+ if (!pd->session) {
pppol2tp_seq_tunnel_show(m, pd->tunnel);
- else
+ } else {
pppol2tp_seq_session_show(m, pd->session);
+ if (pd->session->deref)
+ pd->session->deref(pd->session);
+ l2tp_session_dec_refcount(pd->session);
+ }
out:
return 0;
@@ -1843,4 +1848,4 @@
MODULE_LICENSE("GPL");
MODULE_VERSION(PPPOL2TP_DRV_VERSION);
MODULE_ALIAS_NET_PF_PROTO(PF_PPPOX, PX_PROTO_OL2TP);
-MODULE_ALIAS_L2TP_PWTYPE(11);
+MODULE_ALIAS_L2TP_PWTYPE(7);
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index 0f5628a..3c7ae04 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -969,9 +969,8 @@
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
IF_DEBUG("qtaguid: iface_stat: create(%s): "
"ifa=%p ifa_label=%s\n",
- ifname, ifa,
- ifa->ifa_label ? ifa->ifa_label : "(null)");
- if (ifa->ifa_label && !strcmp(ifname, ifa->ifa_label))
+ ifname, ifa, ifa->ifa_label);
+ if (!strcmp(ifname, ifa->ifa_label))
break;
}
}
@@ -1209,10 +1208,6 @@
pr_err_ratelimited("qtaguid[%d]: %s(): no par->in/out?!!\n",
par->hooknum, __func__);
BUG();
- } else if (unlikely(!el_dev->name)) {
- pr_err_ratelimited("qtaguid[%d]: %s(): no dev->name?!!\n",
- par->hooknum, __func__);
- BUG();
} else {
proto = ipx_proto(skb, par);
MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n",
@@ -1637,8 +1632,6 @@
if (unlikely(!el_dev)) {
pr_info("qtaguid[%d]: no par->in/out?!!\n", par->hooknum);
- } else if (unlikely(!el_dev->name)) {
- pr_info("qtaguid[%d]: no dev->name?!!\n", par->hooknum);
} else {
int proto = ipx_proto(skb, par);
MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n",
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8ab0974..cb76ff3 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -3702,6 +3702,8 @@
return -EBUSY;
if (copy_from_user(&val, optval, sizeof(val)))
return -EFAULT;
+ if (val > INT_MAX)
+ return -EINVAL;
po->tp_reserve = val;
return 0;
}
@@ -4247,6 +4249,8 @@
rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
if (unlikely(rb->frames_per_block == 0))
goto out;
+ if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+ goto out;
if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
req->tp_frame_nr))
goto out;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 6734420..14346dc 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6861,6 +6861,9 @@
if (sock->state != SS_UNCONNECTED)
goto out;
+ if (!sctp_sstate(sk, LISTENING) && !sctp_sstate(sk, CLOSED))
+ goto out;
+
/* If backlog is zero, disable listening. */
if (!backlog) {
if (sctp_sstate(sk, CLOSED))
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index e318878..35ad69f 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -70,7 +70,7 @@
MODULE_PARM_DESC(bss_entries_limit,
"limit to number of scan BSS entries (per wiphy, default 1000)");
-#define IEEE80211_SCAN_RESULT_EXPIRE (7 * HZ)
+#define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
static void bss_free(struct cfg80211_internal_bss *bss)
{
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c
index 3b693e9..12ba833 100644
--- a/sound/core/seq/seq_lock.c
+++ b/sound/core/seq/seq_lock.c
@@ -28,19 +28,16 @@
/* wait until all locks are released */
void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line)
{
- int max_count = 5 * HZ;
+ int warn_count = 5 * HZ;
if (atomic_read(lockp) < 0) {
pr_warn("ALSA: seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line);
return;
}
while (atomic_read(lockp) > 0) {
- if (max_count == 0) {
- pr_warn("ALSA: seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line);
- break;
- }
+ if (warn_count-- == 0)
+ pr_warn("ALSA: seq_lock: waiting [%d left] in %s:%d\n", atomic_read(lockp), file, line);
schedule_timeout_uninterruptible(1);
- max_count--;
}
}
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h
index f676931..c3768cd 100644
--- a/sound/firewire/lib.h
+++ b/sound/firewire/lib.h
@@ -45,7 +45,7 @@
struct snd_rawmidi_substream *substream;
snd_fw_async_midi_port_fill fill;
- unsigned int consume_bytes;
+ int consume_bytes;
};
int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port,
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c
index e629b88..474b06d 100644
--- a/sound/firewire/oxfw/oxfw.c
+++ b/sound/firewire/oxfw/oxfw.c
@@ -226,11 +226,11 @@
if (err < 0)
goto error;
- err = detect_quirks(oxfw);
+ err = snd_oxfw_stream_discover(oxfw);
if (err < 0)
goto error;
- err = snd_oxfw_stream_discover(oxfw);
+ err = detect_quirks(oxfw);
if (err < 0)
goto error;
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 4c8ff29..d5873ee 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -621,7 +621,7 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
- .ignore_suspend = 1,
+ .nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
@@ -634,7 +634,6 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
- .ignore_suspend = 1,
.nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
@@ -661,6 +660,7 @@
| SND_SOC_DAIFMT_CBS_CFS,
.be_hw_params_fixup = byt_rt5640_codec_fixup,
.ignore_suspend = 1,
+ .nonatomic = true,
.dpcm_playback = 1,
.dpcm_capture = 1,
.init = byt_rt5640_init,
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 35f591e..eabff3a 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -235,7 +235,6 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
- .ignore_suspend = 1,
.nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
@@ -249,7 +248,6 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
- .ignore_suspend = 1,
.nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,