Merge "battery: handle early/late suspend/resume of i2c bus"
diff --git a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
index d99b214..b0c5b57 100644
--- a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
+++ b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
@@ -46,6 +46,11 @@
1 : Forces a fresh measurement for calibration values at the same time
measurement is taken.
- qcom,adc-full-scale-code: Full scale code with offset removed.
+- pinctrl-names: should be "default" (see pinctrl binding [0]).
+- pinctrl-0: a phandle pointing to the pin settings for the
+ device (see pinctrl binding [0]).
+
+[0]: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Client required property:
- qcom,<consumer name>-vadc : The phandle to the corresponding vadc device.
diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt
index aede546..6b40b30 100644
--- a/Documentation/devicetree/bindings/platform/msm/ipa.txt
+++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt
@@ -79,6 +79,8 @@
- qcom,rx-polling-sleep-ms: Receive Polling Timeout in millisecond,
default is 1 millisecond.
- qcom,ipa-polling-iteration: IPA Polling Iteration Count,default is 40.
+- qcom,mhi-event-ring-id-limits: Two elements property. Start and End limits
+ for MHI event rings ids.
- qcom,ipa-tz-unlock-reg: Register start addresses and ranges which
need to be unlocked by TZ.
diff --git a/Documentation/devicetree/bindings/soc/qcom/dcc.txt b/Documentation/devicetree/bindings/soc/qcom/dcc.txt
index 8a9761c..5150459 100644
--- a/Documentation/devicetree/bindings/soc/qcom/dcc.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/dcc.txt
@@ -35,6 +35,14 @@
"atb" : To send captured data over ATB to a trace sink
"sram" : To save captured data in dcc internal SRAM.
+- qcom,curr-link-list: int, To specify the link list to use for the default list.
+
+- qcom,link-list: The values to be programmed into the default link list.
+ The enum values for DCC operations is defined in dt-bindings/soc/qcom,dcc_v2.h
+ The following gives basic structure to be used for each operation:
+ <DCC_operation addr val apb_bus>
+ val is to be interpreted based on what operation is to be performed.
+
Example:
dcc: dcc@4b3000 {
@@ -47,6 +55,13 @@
clocks = <&clock_gcc clk_gcc_dcc_ahb_clk>;
clock-names = "dcc_clk";
+ qcom,curr-link-list = <2>;
+ qcom,link-list = <DCC_READ 0x1740300 6 0>,
+ <DCC_READ 0x1620500 4 0>,
+ <DCC_READ 0x7840000 1 0>,
+ <DCC_READ 0x7841010 12 0>,
+ <DCC_READ 0x7842000 16 0>,
+ <DCC_READ 0x7842500 2 0>;
qcom,save-reg;
};
diff --git a/Makefile b/Makefile
index 598dd1d..dd43551 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 9
-SUBLEVEL = 56
+SUBLEVEL = 58
EXTRAVERSION =
NAME = Roaring Lionus
diff --git a/arch/arm/boot/dts/qcom/pmxpoorwills.dtsi b/arch/arm/boot/dts/qcom/pmxpoorwills.dtsi
index e3f154b..2106759 100644
--- a/arch/arm/boot/dts/qcom/pmxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/pmxpoorwills.dtsi
@@ -85,6 +85,55 @@
interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>;
};
};
+
+ pmxpoorwills_vadc: vadc@3100 {
+ compatible = "qcom,qpnp-vadc-hc";
+ reg = <0x3100 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "eoc-int-en-set";
+ qcom,adc-full-scale-code = <0x70e4>;
+ qcom,adc-vdd-reference = <1875>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ambient_therm_default>;
+
+ chan@6 {
+ label = "die_temp";
+ reg = <6>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <3>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ qcom,cal-val = <0>;
+ };
+
+ chan@0 {
+ label = "ref_gnd";
+ reg = <0>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ qcom,cal-val = <0>;
+ };
+
+ chan@1 {
+ label = "ref_1250v";
+ reg = <1>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ qcom,cal-val = <0>;
+ };
+ };
};
qcom,pmxpoorwills@1 {
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts
index 8b5eee0..15129c7 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts
@@ -32,3 +32,76 @@
&qnand_1 {
status = "ok";
};
+
+&pmxpoorwills_vadc {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4d {
+ label = "pa_therm1";
+ reg = <0x4d>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4e {
+ label = "pa_therm2";
+ reg = <0x4e>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4f {
+ label = "mdm_case_therm";
+ reg = <0x4f>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@52 {
+ label = "ambient_therm";
+ reg = <0x52>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
index 0f84228..8d7e377 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
@@ -32,3 +32,76 @@
&qnand_1 {
status = "ok";
};
+
+&pmxpoorwills_vadc {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4d {
+ label = "pa_therm1";
+ reg = <0x4d>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4e {
+ label = "pa_therm2";
+ reg = <0x4e>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4f {
+ label = "mdm_case_therm";
+ reg = <0x4f>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@52 {
+ label = "ambient_therm";
+ reg = <0x52>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
index 8181fa8..2b0fa5c 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
@@ -921,3 +921,12 @@
};
};
};
+
+&pmxpoorwills_gpios {
+ ambient_therm {
+ ambient_therm_default: ambient_therm_default {
+ pins = "gpio2";
+ bias-high-impedance;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-thermal.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-thermal.dtsi
new file mode 100644
index 0000000..5a4810a
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-thermal.dtsi
@@ -0,0 +1,293 @@
+/* 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/thermal/thermal.h>
+
+&soc {
+ qmi-tmd-devices {
+ compatible = "qcom,qmi_cooling_devices";
+
+ modem {
+ qcom,instance-id = <0x0>;
+
+ modem_pa: modem_pa {
+ qcom,qmi-dev-name = "pa";
+ #cooling-cells = <2>;
+ };
+
+ modem_proc: modem_proc {
+ qcom,qmi-dev-name = "modem";
+ #cooling-cells = <2>;
+ };
+
+ modem_current: modem_current {
+ qcom,qmi-dev-name = "modem_current";
+ #cooling-cells = <2>;
+ };
+
+ modem_skin: modem_skin {
+ qcom,qmi-dev-name = "modem_skin";
+ #cooling-cells = <2>;
+ };
+
+ modem_vdd: modem_vdd {
+ qcom,qmi-dev-name = "cpuv_restriction_cold";
+ #cooling-cells = <2>;
+ };
+ };
+
+ adsp {
+ qcom,instance-id = <0x1>;
+
+ adsp_vdd: adsp_vdd {
+ qcom,qmi-dev-name = "cpuv_restriction_cold";
+ #cooling-cells = <2>;
+ };
+ };
+ };
+};
+
+&thermal_zones {
+ aoss-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 0>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mdm-q6-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 1>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ ddrss-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 2>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpu-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 3>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mdm-core-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 4>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mdm-vpe-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 5>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ aoss-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 0>;
+ tracks-low;
+ trips {
+ aoss_trip: aoss-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ modem_vdd_cdev {
+ trip = <&aoss_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&aoss_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ };
+ };
+
+ mdm-q6-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 1>;
+ tracks-low;
+ trips {
+ mdm_q6_trip: mdm-q6-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ modem_vdd_cdev {
+ trip = <&mdm_q6_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&mdm_q6_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ };
+ };
+
+ ddrss-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 2>;
+ tracks-low;
+ trips {
+ ddrss_trip: ddrss-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ modem_vdd_cdev {
+ trip = <&ddrss_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&ddrss_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ };
+ };
+
+ cpu-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 3>;
+ tracks-low;
+ trips {
+ cpu_trip: cpu-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ modem_vdd_cdev {
+ trip = <&cpu_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&cpu_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ };
+ };
+
+ mdm-core-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 4>;
+ tracks-low;
+ trips {
+ mdm_trip: mdm-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ modem_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ };
+ };
+
+ mdm-vpe-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 5>;
+ tracks-low;
+ trips {
+ mdm_vpe_trip: mdm-vpe-trip {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ modem_vdd_cdev {
+ trip = <&mdm_vpe_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&mdm_vpe_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index 7875f19..71556ba 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -51,6 +51,7 @@
device-type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x0>;
+ #cooling-cells = <2>;
};
};
@@ -263,77 +264,7 @@
#thermal-sensor-cells = <1>;
};
- thermal_zones: thermal-zones {
- mpm-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-governor = "user_space";
- thermal-sensors = <&tsens0 0>;
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- q6-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-governor = "user_space";
- thermal-sensors = <&tsens0 1>;
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- ctile-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-governor = "user_space";
- thermal-sensors = <&tsens0 2>;
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- cpu-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-governor = "user_space";
- thermal-sensors = <&tsens0 3>;
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- mdm-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-governor = "user_space";
- thermal-sensors = <&tsens0 4>;
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
- };
+ thermal_zones: thermal-zones { };
qcom,ipa_fws {
compatible = "qcom,pil-tz-generic";
@@ -492,3 +423,4 @@
#include "sdxpoorwills-smp2p.dtsi"
#include "sdxpoorwills-usb.dtsi"
#include "sdxpoorwills-bus.dtsi"
+#include "sdxpoorwills-thermal.dtsi"
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index 877406f..0d35667 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -217,6 +217,7 @@
CONFIG_QCOM_DLOAD_MODE=y
CONFIG_POWER_SUPPLY=y
CONFIG_SMB138X_CHARGER=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_THERMAL=y
CONFIG_THERMAL_QPNP=y
CONFIG_THERMAL_TSENS=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index d860595..6c24910 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -210,6 +210,7 @@
CONFIG_QCOM_DLOAD_MODE=y
CONFIG_POWER_SUPPLY=y
CONFIG_SMB138X_CHARGER=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_THERMAL=y
CONFIG_THERMAL_QPNP=y
CONFIG_THERMAL_TSENS=y
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm670.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm670.dtsi
index 25a332b..715b59c 100644
--- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm670.dtsi
@@ -63,6 +63,7 @@
#iommu-cells = <2>;
qcom,skip-init;
qcom,use-3-lvl-tables;
+ qcom,no-asid-retention;
#global-interrupts = <1>;
#size-cells = <1>;
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index df5a970..502b2fe 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -116,7 +116,6 @@
#size-cells = <0>;
interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "eoc-int-en-set";
- qcom,adc-bit-resolution = <15>;
qcom,adc-vdd-reference = <1875>;
chan@6 {
@@ -280,7 +279,6 @@
#size-cells = <0>;
interrupts = <0x0 0x34 0x0 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "eoc-int-en-set";
- qcom,adc-bit-resolution = <15>;
qcom,adc-vdd-reference = <1875>;
qcom,adc_tm-vadc = <&pm660_vadc>;
qcom,decimation = <0>;
@@ -338,7 +336,7 @@
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
qcom,btm-channel-number = <0x80>;
- qcom,vadc-thermal-node;
+ qcom,thermal-node;
};
chan@4f {
@@ -349,7 +347,7 @@
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
qcom,btm-channel-number = <0x88>;
- qcom,vadc-thermal-node;
+ qcom,thermal-node;
};
};
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi
index 013ac48..dc3ffda 100644
--- a/arch/arm64/boot/dts/qcom/pm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi
@@ -138,7 +138,6 @@
#size-cells = <0>;
interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "eoc-int-en-set";
- qcom,adc-bit-resolution = <15>;
qcom,adc-vdd-reference = <1875>;
chan@6 {
@@ -185,7 +184,6 @@
#size-cells = <0>;
interrupts = <0x0 0x34 0x0 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "eoc-int-en-set";
- qcom,adc-bit-resolution = <15>;
qcom,adc-vdd-reference = <1875>;
qcom,adc_tm-vadc = <&pm8998_vadc>;
qcom,decimation = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi b/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi
index 6f22264..4f5a9b1 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi
@@ -12,6 +12,7 @@
#include <dt-bindings/msm/msm-bus-ids.h>
#include <dt-bindings/soc/qcom,tcs-mbox.h>
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
&soc {
ad_hoc_bus: ad-hoc-bus {
@@ -309,7 +310,6 @@
qcom,bcm-dev;
};
-
/*Buses*/
fab_aggre1_noc: fab-aggre1_noc {
cell-id = <MSM_BUS_FAB_A1_NOC>;
@@ -318,7 +318,6 @@
qcom,base-name = "aggre1_noc-base";
qcom,qos-off = <4096>;
qcom,base-offset = <16384>;
- qcom,bypass-qos-prg;
qcom,bus-type = <1>;
clocks = <>;
};
@@ -330,7 +329,6 @@
qcom,base-name = "aggre2_noc-base";
qcom,qos-off = <2048>;
qcom,base-offset = <12288>;
- qcom,bypass-qos-prg;
qcom,bus-type = <1>;
clocks = <>;
};
@@ -340,8 +338,6 @@
label = "fab-camnoc_virt";
qcom,fab-dev;
qcom,base-name = "camnoc_virt-base";
- qcom,qos-off = <0>;
- qcom,base-offset = <0>;
qcom,bypass-qos-prg;
clocks = <>;
};
@@ -351,8 +347,6 @@
label = "fab-config_noc";
qcom,fab-dev;
qcom,base-name = "config_noc-base";
- qcom,qos-off = <0>;
- qcom,base-offset = <0>;
qcom,bypass-qos-prg;
qcom,bus-type = <1>;
clocks = <>;
@@ -363,8 +357,6 @@
label = "fab-dc_noc";
qcom,fab-dev;
qcom,base-name = "dc_noc-base";
- qcom,qos-off = <0>;
- qcom,base-offset = <0>;
qcom,bypass-qos-prg;
qcom,bus-type = <1>;
clocks = <>;
@@ -375,8 +367,6 @@
label = "fab-gladiator_noc";
qcom,fab-dev;
qcom,base-name = "gladiator_noc-base";
- qcom,qos-off = <0>;
- qcom,base-offset = <0>;
qcom,bypass-qos-prg;
qcom,bus-type = <1>;
clocks = <>;
@@ -387,8 +377,6 @@
label = "fab-ipa_virt";
qcom,fab-dev;
qcom,base-name = "ipa_virt-base";
- qcom,qos-off = <0>;
- qcom,base-offset = <0>;
qcom,bypass-qos-prg;
clocks = <>;
};
@@ -398,8 +386,6 @@
label = "fab-mc_virt";
qcom,fab-dev;
qcom,base-name = "mc_virt-base";
- qcom,qos-off = <0>;
- qcom,base-offset = <0>;
qcom,bypass-qos-prg;
clocks = <>;
};
@@ -411,7 +397,6 @@
qcom,base-name = "mem_noc-base";
qcom,qos-off = <4096>;
qcom,base-offset = <65536>;
- qcom,bypass-qos-prg;
qcom,bus-type = <1>;
clocks = <>;
};
@@ -423,7 +408,6 @@
qcom,base-name = "mmss_noc-base";
qcom,qos-off = <4096>;
qcom,base-offset = <36864>;
- qcom,bypass-qos-prg;
qcom,bus-type = <1>;
clocks = <>;
};
@@ -435,7 +419,6 @@
qcom,base-name = "system_noc-base";
qcom,qos-off = <4096>;
qcom,base-offset = <36864>;
- qcom,bypass-qos-prg;
qcom,bus-type = <1>;
clocks = <>;
};
@@ -445,8 +428,6 @@
label = "fab-mc_virt_display";
qcom,fab-dev;
qcom,base-name = "mc_virt-base";
- qcom,qos-off = <0>;
- qcom,base-offset = <0>;
qcom,bypass-qos-prg;
clocks = <>;
};
@@ -468,14 +449,11 @@
label = "fab-mmss_noc_display";
qcom,fab-dev;
qcom,base-name = "mmss_noc-base";
- qcom,qos-off = <4096>;
- qcom,base-offset = <36864>;
qcom,bypass-qos-prg;
qcom,bus-type = <1>;
clocks = <>;
};
-
/*Masters*/
mas_qhm_a1noc_cfg: mas-qhm-a1noc-cfg {
@@ -492,12 +470,9 @@
label = "mas-qhm-qup1";
qcom,buswidth = <4>;
qcom,agg-ports = <1>;
- qcom,qport = <16>;
qcom,connections = <&slv_qns_a1noc_snoc>;
qcom,bus-dev = <&fab_aggre1_noc>;
qcom,bcms = <&bcm_qup0>;
- qcom,ap-owned;
- qcom,prio = <0>;
};
mas_qhm_tsif: mas-qhm-tsif {
@@ -571,11 +546,8 @@
label = "mas-qhm-qdss-bam";
qcom,buswidth = <4>;
qcom,agg-ports = <1>;
- qcom,qport = <17>;
qcom,connections = <&slv_qns_a2noc_snoc>;
qcom,bus-dev = <&fab_aggre2_noc>;
- qcom,ap-owned;
- qcom,prio = <0>;
};
mas_qhm_qup2: mas-qhm-qup2 {
@@ -583,12 +555,9 @@
label = "mas-qhm-qup2";
qcom,buswidth = <4>;
qcom,agg-ports = <1>;
- qcom,qport = <0>;
qcom,connections = <&slv_qns_a2noc_snoc>;
qcom,bus-dev = <&fab_aggre2_noc>;
qcom,bcms = <&bcm_qup0>;
- qcom,ap-owned;
- qcom,prio = <0>;
};
mas_qnm_cnoc: mas-qnm-cnoc {
@@ -626,6 +595,8 @@
qcom,bus-dev = <&fab_aggre2_noc>;
qcom,ap-owned;
qcom,prio = <2>;
+ qcom,defer-init-qos;
+ qcom,node-qos-bcms = <7035 0 1>;
};
mas_xm_qdss_etr: mas-xm-qdss-etr {
@@ -650,6 +621,12 @@
qcom,bus-dev = <&fab_aggre2_noc>;
qcom,ap-owned;
qcom,prio = <2>;
+ qcom,node-qos-clks {
+ clocks =
+ <&clock_gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>;
+ clock-names =
+ "clk-usb3-prim-axi-no-rate";
+ };
};
mas_qxm_camnoc_hf0_uncomp: mas-qxm-camnoc-hf0-uncomp {
@@ -837,7 +814,7 @@
qcom,bus-dev = <&fab_mem_noc>;
qcom,bcms = <&bcm_sh3>;
qcom,ap-owned;
- qcom,prio = <6>;
+ qcom,prio = <7>;
};
mas_qhm_memnoc_cfg: mas-qhm-memnoc-cfg {
@@ -874,6 +851,7 @@
qcom,ap-owned;
qcom,prio = <0>;
qcom,forwarding;
+ qcom,node-qos-bcms = <7012 0 1>;
};
mas_qnm_mnoc_sf: mas-qnm-mnoc-sf {
@@ -888,6 +866,7 @@
qcom,ap-owned;
qcom,prio = <0>;
qcom,forwarding;
+ qcom,node-qos-bcms = <7012 0 1>;
};
mas_qnm_snoc_gc: mas-qnm-snoc-gc {
@@ -950,6 +929,7 @@
qcom,ap-owned;
qcom,prio = <0>;
qcom,forwarding;
+ qcom,node-qos-bcms = <7012 0 1>;
};
mas_qxm_camnoc_hf1: mas-qxm-camnoc-hf1 {
@@ -964,6 +944,7 @@
qcom,ap-owned;
qcom,prio = <0>;
qcom,forwarding;
+ qcom,node-qos-bcms = <7012 0 1>;
};
mas_qxm_camnoc_sf: mas-qxm-camnoc-sf {
@@ -978,6 +959,7 @@
qcom,ap-owned;
qcom,prio = <0>;
qcom,forwarding;
+ qcom,node-qos-bcms = <7012 0 1>;
};
mas_qxm_mdp0: mas-qxm-mdp0 {
@@ -992,6 +974,7 @@
qcom,ap-owned;
qcom,prio = <0>;
qcom,forwarding;
+ qcom,node-qos-bcms = <7012 0 1>;
};
mas_qxm_mdp1: mas-qxm-mdp1 {
@@ -1006,6 +989,7 @@
qcom,ap-owned;
qcom,prio = <0>;
qcom,forwarding;
+ qcom,node-qos-bcms = <7012 0 1>;
};
mas_qxm_rot: mas-qxm-rot {
@@ -1020,6 +1004,7 @@
qcom,ap-owned;
qcom,prio = <0>;
qcom,forwarding;
+ qcom,node-qos-bcms = <7012 0 1>;
};
mas_qxm_venus0: mas-qxm-venus0 {
@@ -1034,6 +1019,7 @@
qcom,ap-owned;
qcom,prio = <0>;
qcom,forwarding;
+ qcom,node-qos-bcms = <7012 0 1>;
};
mas_qxm_venus1: mas-qxm-venus1 {
@@ -1048,6 +1034,7 @@
qcom,ap-owned;
qcom,prio = <0>;
qcom,forwarding;
+ qcom,node-qos-bcms = <7012 0 1>;
};
mas_qxm_venus_arm9: mas-qxm-venus-arm9 {
@@ -1062,6 +1049,7 @@
qcom,ap-owned;
qcom,prio = <0>;
qcom,forwarding;
+ qcom,node-qos-bcms = <7012 0 1>;
};
mas_qhm_snoc_cfg: mas-qhm-snoc-cfg {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
index 2bf00fb..c0834a50 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
@@ -908,7 +908,7 @@
qupv3_se12_2uart_active: qupv3_se12_2uart_active {
mux {
pins = "gpio51", "gpio52";
- function = "qup9";
+ function = "qup12";
};
config {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
index 1925989..616980c 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
@@ -123,7 +123,7 @@
};
&int_codec {
- qcom,model = "sdm660-skuw-snd-card";
+ qcom,model = "sdm670-skuw-snd-card";
qcom,audio-routing =
"RX_BIAS", "INT_MCLK0",
"SPK_RX_BIAS", "INT_MCLK0",
diff --git a/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
index 2a61e18..53213f8 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
@@ -482,109 +482,12 @@
compatible = "qcom,msm-ext-disp-audio-codec-rx";
};
};
-
- sde_dp: qcom,dp_display@0{
- cell-index = <0>;
- compatible = "qcom,dp-display";
-
- gdsc-supply = <&mdss_core_gdsc>;
- vdda-1p2-supply = <&pm660_l1>;
- vdda-0p9-supply = <&pm660l_l1>;
-
- reg = <0xae90000 0xa84>,
- <0x88eaa00 0x200>,
- <0x88ea200 0x200>,
- <0x88ea600 0x200>,
- <0xaf02000 0x1a0>,
- <0x780000 0x621c>,
- <0x88ea030 0x10>,
- <0x88e8000 0x20>,
- <0x0aee1000 0x034>;
- reg-names = "dp_ctrl", "dp_phy", "dp_ln_tx0", "dp_ln_tx1",
- "dp_mmss_cc", "qfprom_physical", "dp_pll",
- "usb3_dp_com", "hdcp_physical";
-
- interrupt-parent = <&mdss_mdp>;
- interrupts = <12 0>;
-
- clocks = <&clock_dispcc DISP_CC_MDSS_DP_AUX_CLK>,
- <&clock_rpmh RPMH_CXO_CLK>,
- <&clock_gcc GCC_USB3_PRIM_CLKREF_CLK>,
- <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
- <&clock_gcc GCC_USB3_PRIM_PHY_PIPE_CLK>,
- <&clock_dispcc DISP_CC_MDSS_DP_LINK_CLK>,
- <&clock_dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>,
- <&clock_dispcc DISP_CC_MDSS_DP_PIXEL_CLK>,
- <&clock_dispcc DISP_CC_MDSS_DP_CRYPTO_CLK>,
- <&clock_dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>,
- <&mdss_dp_pll DP_VCO_DIVIDED_CLK_SRC_MUX>;
- clock-names = "core_aux_clk", "core_usb_ref_clk_src",
- "core_usb_ref_clk", "core_usb_cfg_ahb_clk",
- "core_usb_pipe_clk", "ctrl_link_clk",
- "ctrl_link_iface_clk", "ctrl_pixel_clk",
- "crypto_clk", "pixel_clk_rcg", "pixel_parent";
-
- qcom,dp-usbpd-detection = <&pm660_pdphy>;
- qcom,ext-disp = <&ext_disp>;
-
- qcom,aux-cfg0-settings = [20 00];
- qcom,aux-cfg1-settings = [24 13 23 1d];
- qcom,aux-cfg2-settings = [28 24];
- qcom,aux-cfg3-settings = [2c 00];
- qcom,aux-cfg4-settings = [30 0a];
- qcom,aux-cfg5-settings = [34 26];
- qcom,aux-cfg6-settings = [38 0a];
- qcom,aux-cfg7-settings = [3c 03];
- qcom,aux-cfg8-settings = [40 bb];
- qcom,aux-cfg9-settings = [44 03];
-
- qcom,max-pclk-frequency-khz = <675000>;
-
- qcom,core-supply-entries {
- #address-cells = <1>;
- #size-cells = <0>;
-
- qcom,core-supply-entry@0 {
- reg = <0>;
- qcom,supply-name = "gdsc";
- qcom,supply-min-voltage = <0>;
- qcom,supply-max-voltage = <0>;
- qcom,supply-enable-load = <0>;
- qcom,supply-disable-load = <0>;
- };
- };
-
- qcom,ctrl-supply-entries {
- #address-cells = <1>;
- #size-cells = <0>;
-
- qcom,ctrl-supply-entry@0 {
- reg = <0>;
- qcom,supply-name = "vdda-1p2";
- qcom,supply-min-voltage = <1200000>;
- qcom,supply-max-voltage = <1200000>;
- qcom,supply-enable-load = <21800>;
- qcom,supply-disable-load = <4>;
- };
- };
-
- qcom,phy-supply-entries {
- #address-cells = <1>;
- #size-cells = <0>;
-
- qcom,phy-supply-entry@0 {
- reg = <0>;
- qcom,supply-name = "vdda-0p9";
- qcom,supply-min-voltage = <880000>;
- qcom,supply-max-voltage = <880000>;
- qcom,supply-enable-load = <36000>;
- qcom,supply-disable-load = <32>;
- };
- };
- };
};
&sde_dp {
+ qcom,dp-usbpd-detection = <&pm660_pdphy>;
+ qcom,ext-disp = <&ext_disp>;
+
pinctrl-names = "mdss_dp_active", "mdss_dp_sleep";
pinctrl-0 = <&sde_dp_aux_active &sde_dp_usbplug_cc_active>;
pinctrl-1 = <&sde_dp_aux_suspend &sde_dp_usbplug_cc_suspend>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi
index 2878184..8a811b7 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi
@@ -9,6 +9,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#include <dt-bindings/clock/mdss-10nm-pll-clk.h>
&soc {
mdss_mdp: qcom,mdss_mdp@ae00000 {
@@ -52,10 +53,13 @@
qcom,sde-ctl-off = <0x2000 0x2200 0x2400
0x2600 0x2800>;
qcom,sde-ctl-size = <0xE4>;
+ qcom,sde-ctl-display-pref = "primary", "primary", "none",
+ "none", "none";
- qcom,sde-mixer-off = <0x45000 0x46000 0x47000
- 0x48000 0x49000 0x4a000>;
+ qcom,sde-mixer-off = <0x45000 0x46000 0x47000 0x0 0x0 0x4a000>;
qcom,sde-mixer-size = <0x320>;
+ qcom,sde-mixer-display-pref = "primary", "primary", "none",
+ "none", "none", "none";
qcom,sde-dspp-top-off = <0x1300>;
qcom,sde-dspp-top-size = <0xc>;
@@ -533,4 +537,85 @@
};
};
+ sde_dp: qcom,dp_display@0{
+ cell-index = <0>;
+ compatible = "qcom,dp-display";
+
+ vdda-1p2-supply = <&pm660_l1>;
+ vdda-0p9-supply = <&pm660l_l1>;
+
+ reg = <0xae90000 0xa84>,
+ <0x88eaa00 0x200>,
+ <0x88ea200 0x200>,
+ <0x88ea600 0x200>,
+ <0xaf02000 0x1a0>,
+ <0x780000 0x621c>,
+ <0x88ea030 0x10>,
+ <0x88e8000 0x20>,
+ <0x0aee1000 0x034>;
+ reg-names = "dp_ctrl", "dp_phy", "dp_ln_tx0", "dp_ln_tx1",
+ "dp_mmss_cc", "qfprom_physical", "dp_pll",
+ "usb3_dp_com", "hdcp_physical";
+
+ interrupt-parent = <&mdss_mdp>;
+ interrupts = <12 0>;
+
+ clocks = <&clock_dispcc DISP_CC_MDSS_DP_AUX_CLK>,
+ <&clock_rpmh RPMH_CXO_CLK>,
+ <&clock_gcc GCC_USB3_PRIM_CLKREF_CLK>,
+ <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+ <&clock_gcc GCC_USB3_PRIM_PHY_PIPE_CLK>,
+ <&clock_dispcc DISP_CC_MDSS_DP_LINK_CLK>,
+ <&clock_dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>,
+ <&clock_dispcc DISP_CC_MDSS_DP_PIXEL_CLK>,
+ <&clock_dispcc DISP_CC_MDSS_DP_CRYPTO_CLK>,
+ <&clock_dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>,
+ <&mdss_dp_pll DP_VCO_DIVIDED_CLK_SRC_MUX>;
+ clock-names = "core_aux_clk", "core_usb_ref_clk_src",
+ "core_usb_ref_clk", "core_usb_cfg_ahb_clk",
+ "core_usb_pipe_clk", "ctrl_link_clk",
+ "ctrl_link_iface_clk", "ctrl_pixel_clk",
+ "crypto_clk", "pixel_clk_rcg", "pixel_parent";
+
+ qcom,aux-cfg0-settings = [20 00];
+ qcom,aux-cfg1-settings = [24 13 23 1d];
+ qcom,aux-cfg2-settings = [28 24];
+ qcom,aux-cfg3-settings = [2c 00];
+ qcom,aux-cfg4-settings = [30 0a];
+ qcom,aux-cfg5-settings = [34 26];
+ qcom,aux-cfg6-settings = [38 0a];
+ qcom,aux-cfg7-settings = [3c 03];
+ qcom,aux-cfg8-settings = [40 bb];
+ qcom,aux-cfg9-settings = [44 03];
+
+ qcom,max-pclk-frequency-khz = <675000>;
+
+ qcom,ctrl-supply-entries {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,ctrl-supply-entry@0 {
+ reg = <0>;
+ qcom,supply-name = "vdda-1p2";
+ qcom,supply-min-voltage = <1200000>;
+ qcom,supply-max-voltage = <1200000>;
+ qcom,supply-enable-load = <21800>;
+ qcom,supply-disable-load = <4>;
+ };
+ };
+
+ qcom,phy-supply-entries {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,phy-supply-entry@0 {
+ reg = <0>;
+ qcom,supply-name = "vdda-0p9";
+ qcom,supply-min-voltage = <880000>;
+ qcom,supply-max-voltage = <880000>;
+ qcom,supply-enable-load = <36000>;
+ qcom,supply-disable-load = <32>;
+ };
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index c87ddc5..02bf8c7 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -347,23 +347,14 @@
CPU_COST_0: core-cost0 {
busy-cost-data = <
300000 14
- 403200 18
- 480000 21
576000 25
- 652800 27
748800 31
- 825600 40
- 902400 43
- 979200 46
- 1056000 50
- 1132800 53
- 1228800 57
+ 998400 46
+ 1209600 57
1324800 84
- 1420800 90
1516800 96
1612800 114
- 1689600 135
- 1766400 141
+ 1708000 139
>;
idle-cost-data = <
12 10 8 6
@@ -372,32 +363,23 @@
CPU_COST_1: core-cost1 {
busy-cost-data = <
300000 256
- 403200 271
- 480000 282
- 576000 296
652800 307
- 748800 321
825600 332
- 902400 369
979200 382
- 1056000 395
1132800 408
- 1209600 421
- 1286400 434
1363200 448
- 1459200 567
- 1536000 586
- 1612800 604
- 1689600 622
- 1766400 641
+ 1563000 586
+ 1747200 641
1843200 659
- 1920000 678
1996800 696
- 2092800 876
+ 2054400 876
2169600 900
- 2246400 924
- 2323200 948
+ 2208000 924
+ 2361600 948
2400000 1170
+ 2457600 1200
+ 2515200 1300
+ 2611200 1400
>;
idle-cost-data = <
100 80 60 40
@@ -406,23 +388,14 @@
CLUSTER_COST_0: cluster-cost0 {
busy-cost-data = <
300000 5
- 403200 7
- 480000 7
576000 7
- 652800 8
748800 8
- 825600 9
- 902400 9
- 979200 9
- 1056000 10
- 1132800 10
- 1228800 10
+ 998400 9
+ 1209600 10
1324800 13
- 1420800 14
1516800 15
1612800 16
- 1689600 19
- 1766400 19
+ 1708000 19
>;
idle-cost-data = <
4 3 2 1
@@ -431,32 +404,23 @@
CLUSTER_COST_1: cluster-cost1 {
busy-cost-data = <
300000 25
- 403200 27
- 480000 28
- 576000 29
652800 30
- 748800 32
825600 33
- 902400 36
979200 38
- 1056000 39
1132800 40
- 1209600 42
- 1286400 43
1363200 44
- 1459200 56
- 1536000 58
- 1612800 60
- 1689600 62
- 1766400 64
+ 1563000 58
+ 1747200 64
1843200 65
- 1920000 67
1996800 69
- 2092800 87
+ 2054400 87
2169600 90
- 2246400 92
- 2323200 94
+ 2208000 92
+ 2361600 94
2400000 117
+ 2457600 120
+ 2515200 130
+ 2611200 140
>;
idle-cost-data = <
4 3 2 1
@@ -1892,7 +1856,6 @@
qcom,ipa-wdi2;
qcom,use-64-bit-dma-mask;
qcom,arm-smmu;
- qcom,smmu-s1-bypass;
qcom,bandwidth-vote-for-ipa;
qcom,msm-bus,name = "ipa";
qcom,msm-bus,num-cases = <4>;
@@ -2009,17 +1972,20 @@
ipa_smmu_ap: ipa_smmu_ap {
compatible = "qcom,ipa-smmu-ap-cb";
+ qcom,smmu-s1-bypass;
iommus = <&apps_smmu 0x720 0x0>;
qcom,iova-mapping = <0x20000000 0x40000000>;
};
ipa_smmu_wlan: ipa_smmu_wlan {
compatible = "qcom,ipa-smmu-wlan-cb";
+ qcom,smmu-s1-bypass;
iommus = <&apps_smmu 0x721 0x0>;
};
ipa_smmu_uc: ipa_smmu_uc {
compatible = "qcom,ipa-smmu-uc-cb";
+ qcom,smmu-s1-bypass;
iommus = <&apps_smmu 0x722 0x0>;
qcom,iova-mapping = <0x40000000 0x20000000>;
};
@@ -2180,31 +2146,31 @@
qcom,msm-bus,num-paths = <2>;
qcom,msm-bus,vectors-KBps =
/* No vote */
- <150 512 0 0>, <1 606 0 0>,
+ <150 512 0 0>, <1 782 0 0>,
/* 400 KB/s*/
<150 512 1046 1600>,
- <1 606 1600 1600>,
+ <1 782 1600 1600>,
/* 20 MB/s */
<150 512 52286 80000>,
- <1 606 80000 80000>,
+ <1 782 80000 80000>,
/* 25 MB/s */
<150 512 65360 100000>,
- <1 606 100000 100000>,
+ <1 782 100000 100000>,
/* 50 MB/s */
<150 512 130718 200000>,
- <1 606 133320 133320>,
+ <1 782 133320 133320>,
/* 100 MB/s */
<150 512 130718 200000>,
- <1 606 150000 150000>,
+ <1 782 150000 150000>,
/* 200 MB/s */
<150 512 261438 400000>,
- <1 606 300000 300000>,
+ <1 782 300000 300000>,
/* 400 MB/s */
<150 512 261438 400000>,
- <1 606 300000 300000>,
+ <1 782 300000 300000>,
/* Max. bandwidth */
<150 512 1338562 4096000>,
- <1 606 1338562 4096000>;
+ <1 782 1338562 4096000>;
qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
100000000 200000000 400000000 4294967295>;
@@ -2743,6 +2709,22 @@
};
};
+&sde_dp {
+ qcom,core-supply-entries {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,core-supply-entry@0 {
+ reg = <0>;
+ qcom,supply-name = "refgen";
+ qcom,supply-min-voltage = <0>;
+ qcom,supply-max-voltage = <0>;
+ qcom,supply-enable-load = <0>;
+ qcom,supply-disable-load = <0>;
+ };
+ };
+};
+
#include "sdm670-audio.dtsi"
#include "sdm670-usb.dtsi"
#include "sdm670-gpu.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qvr-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qvr-audio-overlay.dtsi
new file mode 100644
index 0000000..77a89f0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-qvr-audio-overlay.dtsi
@@ -0,0 +1,52 @@
+/*
+ * 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 "sdm845-audio-overlay.dtsi"
+
+&snd_934x {
+ qcom,model = "sdm845-qvr-tavil-snd-card";
+
+ qcom,audio-routing =
+ "AIF4 VI", "MCLK",
+ "RX_BIAS", "MCLK",
+ "MADINPUT", "MCLK",
+ "AMIC1", "Handset Mic",
+ "AMIC2", "MIC BIAS2",
+ "MIC BIAS2", "Headset Mic",
+ "DMIC0", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic0",
+ "DMIC1", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic1",
+ "DMIC2", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic2",
+ "DMIC3", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic3",
+ "DMIC4", "MIC BIAS4",
+ "MIC BIAS4", "Digital Mic4",
+ "DMIC5", "MIC BIAS4",
+ "MIC BIAS4", "Digital Mic5",
+ "SpkrLeft IN", "SPK1 OUT";
+
+ qcom,msm-mbhc-hphl-swh = <0>;
+ /delete-property/ qcom,hph-en0-gpio;
+ /delete-property/ qcom,hph-en1-gpio;
+ /delete-property/ qcom,usbc-analog-en1-gpio;
+ /delete-property/ qcom,usbc-analog-en2-gpio;
+ /delete-property/ pinctrl-names;
+ /delete-property/ pinctrl-0;
+ /delete-property/ pinctrl-1;
+
+ qcom,wsa-max-devs = <1>;
+ qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
+ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrLeft";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qvr-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-qvr-overlay.dts
index fb99157..b1b81d1 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qvr-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-qvr-overlay.dts
@@ -21,6 +21,7 @@
#include "sdm845-sde-display.dtsi"
#include "sdm845-qvr.dtsi"
+#include "sdm845-qvr-audio-overlay.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM845 v2 QVR";
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 22a6b5d..86705d6 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -25,6 +25,7 @@
#include <dt-bindings/spmi/spmi.h>
#include <dt-bindings/thermal/thermal.h>
#include <dt-bindings/msm/msm-bus-ids.h>
+#include <dt-bindings/soc/qcom,dcc_v2.h>
#define MHZ_TO_MBPS(mhz, w) ((mhz * 1000000 * w) / (1024 * 1024))
@@ -2793,6 +2794,214 @@
reg-names = "dcc-base", "dcc-ram-base";
dcc-ram-offset = <0x6000>;
+
+ qcom,curr-link-list = <2>;
+ qcom,link-list = <DCC_READ 0x1740300 6 0>,
+ <DCC_READ 0x1620500 4 0>,
+ <DCC_READ 0x7840000 1 0>,
+ <DCC_READ 0x7841010 12 0>,
+ <DCC_READ 0x7842000 16 0>,
+ <DCC_READ 0x7842500 2 0>,
+ <DCC_LOOP 7 0 0>,
+ <DCC_READ 0x7841000 1 0>,
+ <DCC_LOOP 1 0 0>,
+ <DCC_LOOP 165 0 0>,
+ <DCC_READ 0x7841008 2 0>,
+ <DCC_LOOP 1 0 0>,
+ <DCC_READ 0x17dc3a84 2 0>,
+ <DCC_READ 0x17db3a84 1 0>,
+ <DCC_READ 0x1301000 2 0>,
+ <DCC_READ 0x17990044 1 0>,
+ <DCC_READ 0x17d45f00 1 0>,
+ <DCC_READ 0x17d45f08 6 0>,
+ <DCC_READ 0x17d45f80 1 0>,
+ <DCC_READ 0x17d47418 1 0>,
+ <DCC_READ 0x17d47570 1 0>,
+ <DCC_READ 0x17d47588 1 0>,
+ <DCC_READ 0x17d43700 1 0>,
+ <DCC_READ 0x17d43708 6 0>,
+ <DCC_READ 0x17d43780 1 0>,
+ <DCC_READ 0x17d44c18 1 0>,
+ <DCC_READ 0x17d44d70 1 0>,
+ <DCC_READ 0x17d44d88 1 0>,
+ <DCC_READ 0x17d41700 1 0>,
+ <DCC_READ 0x17d41708 6 0>,
+ <DCC_READ 0x17d41780 1 0>,
+ <DCC_READ 0x17d42c18 1 0>,
+ <DCC_READ 0x17d42d70 1 0>,
+ <DCC_READ 0x17d42d88 1 0>,
+ <DCC_WRITE 0x69ea00c 0x600007 1>,
+ <DCC_WRITE 0x69ea01c 0x136800 1>,
+ <DCC_READ 0x69ea014 1 1>,
+ <DCC_WRITE 0x69ea01c 0x136810 1>,
+ <DCC_READ 0x69ea014 1 1>,
+ <DCC_WRITE 0x69ea01c 0x136820 1>,
+ <DCC_READ 0x69ea014 1 1>,
+ <DCC_WRITE 0x69ea01c 0x136830 1>,
+ <DCC_READ 0x69ea014 1 1>,
+ <DCC_WRITE 0x69ea01c 0x136840 1>,
+ <DCC_READ 0x69ea014 1 1>,
+ <DCC_WRITE 0x69ea01c 0x136850 1>,
+ <DCC_READ 0x69ea014 1 1>,
+ <DCC_WRITE 0x69ea01c 0x136860 1>,
+ <DCC_READ 0x69ea014 1 1>,
+ <DCC_WRITE 0x69ea01c 0x136870 1>,
+ <DCC_READ 0x69ea014 1 1>,
+ <DCC_WRITE 0x069ea01C 0x0003e9a0 1>,
+ <DCC_WRITE 0x069ea01C 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x0003c0a0 1>,
+ <DCC_WRITE 0x069ea01c 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x0003d1a0 1>,
+ <DCC_WRITE 0x069ea01C 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x0003d2a0 1>,
+ <DCC_WRITE 0x069ea01c 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01C 0x0003d5a0 1>,
+ <DCC_WRITE 0x069ea01C 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01C 0x0003d6a0 1>,
+ <DCC_WRITE 0x069ea01C 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x001368a0 1>,
+ <DCC_WRITE 0x069ea01c 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x0003b1a0 1>,
+ <DCC_WRITE 0x069ea01c 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x0003b2a0 1>,
+ <DCC_WRITE 0x069ea01c 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x0003b5a0 1>,
+ <DCC_WRITE 0x069ea01c 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x0003b6a0 1>,
+ <DCC_WRITE 0x069ea01c 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x0003c2a0 1>,
+ <DCC_WRITE 0x069ea01c 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x0003c5a0 1>,
+ <DCC_WRITE 0x069ea01c 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x0003c6a0 1>,
+ <DCC_WRITE 0x069ea01c 0x001368a0 1>,
+ <DCC_READ 0x069ea014 1 1>,
+ <DCC_WRITE 0x069ea01c 0x00f1e000 1>,
+ <DCC_WRITE 0x069ea008 0x00000007 1>,
+ <DCC_READ 0x013e7e00 31 0>,
+ <DCC_READ 0x01132100 1 0>,
+ <DCC_READ 0x01136044 4 0>,
+ <DCC_READ 0x011360b0 1 0>,
+ <DCC_READ 0x0113e030 2 0>,
+ <DCC_READ 0x01141000 1 0>,
+ <DCC_READ 0x01142028 1 0>,
+ <DCC_READ 0x01148058 4 0>,
+ <DCC_READ 0x01160410 3 0>,
+ <DCC_READ 0x011604a0 1 0>,
+ <DCC_READ 0x011604b8 1 0>,
+ <DCC_READ 0x01165804 1 0>,
+ <DCC_READ 0x01166418 1 0>,
+ <DCC_READ 0x011b2100 1 0>,
+ <DCC_READ 0x011b6044 4 0>,
+ <DCC_READ 0x011be030 2 0>,
+ <DCC_READ 0x011c1000 1 0>,
+ <DCC_READ 0x011c2028 1 0>,
+ <DCC_READ 0x011c8058 4 0>,
+ <DCC_READ 0x011e0410 3 0>,
+ <DCC_READ 0x011e04a0 1 0>,
+ <DCC_READ 0x011e04b8 1 0>,
+ <DCC_READ 0x011e5804 1 0>,
+ <DCC_READ 0x011e6418 1 0>,
+ <DCC_READ 0x01232100 1 0>,
+ <DCC_READ 0x01236044 4 0>,
+ <DCC_READ 0x012360B0 1 0>,
+ <DCC_READ 0x0123E030 2 0>,
+ <DCC_READ 0x01241000 1 0>,
+ <DCC_READ 0x01242028 1 0>,
+ <DCC_READ 0x01248058 4 0>,
+ <DCC_READ 0x01260410 3 0>,
+ <DCC_READ 0x012604a0 1 0>,
+ <DCC_READ 0x012604b8 1 0>,
+ <DCC_READ 0x01265804 1 0>,
+ <DCC_READ 0x01266418 1 0>,
+ <DCC_READ 0x012b2100 1 0>,
+ <DCC_READ 0x012b6044 3 0>,
+ <DCC_READ 0x012b6050 1 0>,
+ <DCC_READ 0x012b60b0 1 0>,
+ <DCC_READ 0x012be030 2 0>,
+ <DCC_READ 0x012c1000 1 0>,
+ <DCC_READ 0x012c2028 1 0>,
+ <DCC_READ 0x012c8058 4 0>,
+ <DCC_READ 0x012e0410 3 0>,
+ <DCC_READ 0x012e04a0 1 0>,
+ <DCC_READ 0x012e04b8 1 0>,
+ <DCC_READ 0x012e5804 1 0>,
+ <DCC_READ 0x012e6418 1 0>,
+ <DCC_READ 0x01380900 8 0>,
+ <DCC_READ 0x01380d00 5 0>,
+ <DCC_READ 0x01350110 4 0>,
+ <DCC_READ 0x01430280 1 0>,
+ <DCC_READ 0x01430288 1 0>,
+ <DCC_READ 0x0143028c 7 0>,
+ <DCC_READ 0x01132100 1 0>,
+ <DCC_READ 0x01136044 4 0>,
+ <DCC_READ 0x011360b0 1 0>,
+ <DCC_READ 0x0113e030 2 0>,
+ <DCC_READ 0x01141000 1 0>,
+ <DCC_READ 0x01142028 1 0>,
+ <DCC_READ 0x01148058 4 0>,
+ <DCC_READ 0x01160410 3 0>,
+ <DCC_READ 0x011604a0 1 0>,
+ <DCC_READ 0x011604b8 1 0>,
+ <DCC_READ 0x01165804 1 0>,
+ <DCC_READ 0x01166418 1 0>,
+ <DCC_READ 0x011b2100 1 0>,
+ <DCC_READ 0x011b6044 4 0>,
+ <DCC_READ 0x011be030 2 0>,
+ <DCC_READ 0x011c1000 1 0>,
+ <DCC_READ 0x011c2028 1 0>,
+ <DCC_READ 0x011c8058 4 0>,
+ <DCC_READ 0x011e0410 3 0>,
+ <DCC_READ 0x011e04a0 1 0>,
+ <DCC_READ 0x011e04b8 1 0>,
+ <DCC_READ 0x011e5804 1 0>,
+ <DCC_READ 0x011e6418 1 0>,
+ <DCC_READ 0x01232100 1 0>,
+ <DCC_READ 0x01236044 4 0>,
+ <DCC_READ 0x012360b0 1 0>,
+ <DCC_READ 0x0123e030 2 0>,
+ <DCC_READ 0x01241000 1 0>,
+ <DCC_READ 0x01242028 1 0>,
+ <DCC_READ 0x01248058 4 0>,
+ <DCC_READ 0x01260410 3 0>,
+ <DCC_READ 0x012604a0 1 0>,
+ <DCC_READ 0x012604b8 1 0>,
+ <DCC_READ 0x01265804 1 0>,
+ <DCC_READ 0x01266418 1 0>,
+ <DCC_READ 0x012b2100 1 0>,
+ <DCC_READ 0x012b6044 3 0>,
+ <DCC_READ 0x012b6050 1 0>,
+ <DCC_READ 0x012b60b0 1 0>,
+ <DCC_READ 0x012be030 2 0>,
+ <DCC_READ 0x012C1000 1 0>,
+ <DCC_READ 0x012C2028 1 0>,
+ <DCC_READ 0x012C8058 4 0>,
+ <DCC_READ 0x012e0410 3 0>,
+ <DCC_READ 0x012e04a0 1 0>,
+ <DCC_READ 0x012e04b8 1 0>,
+ <DCC_READ 0x012e5804 1 0>,
+ <DCC_READ 0x012e6418 1 0>,
+ <DCC_READ 0x01380900 8 0>,
+ <DCC_READ 0x01380d00 5 0>,
+ <DCC_READ 0x01350110 4 0>,
+ <DCC_READ 0x01430280 1 0>,
+ <DCC_READ 0x01430288 1 0>,
+ <DCC_READ 0x0143028c 7 0>,
+ <DCC_READ 0x0c201244 1 0>,
+ <DCC_READ 0x0c202244 1 0>;
};
qcom,msm-core@780000 {
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index 784a986..144ba27 100644
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -441,6 +441,7 @@
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
CONFIG_MMC_CQ_HCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 6c29dff..a3ddc74 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -435,6 +435,7 @@
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
CONFIG_MMC_CQ_HCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index cdfa1eb..0300ef5 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -7,6 +7,9 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_SCHED_WALT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_RCU_EXPERT=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_RCU_NOCB_CPU=y
@@ -237,6 +240,7 @@
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
CONFIG_MEMORY_STATE_TIME=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
index ddd1c91..c5d3517 100644
--- a/arch/mips/include/asm/irq.h
+++ b/arch/mips/include/asm/irq.h
@@ -18,7 +18,7 @@
#include <irq.h>
#define IRQ_STACK_SIZE THREAD_SIZE
-#define IRQ_STACK_START (IRQ_STACK_SIZE - sizeof(unsigned long))
+#define IRQ_STACK_START (IRQ_STACK_SIZE - 16)
extern void *irq_stack[NR_CPUS];
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index e9385bc..9ade60c 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -2386,7 +2386,6 @@
break;
default:
/* Reserved R6 ops */
- pr_err("Reserved MIPS R6 CMP.condn.S operation\n");
return SIGILL;
}
}
@@ -2460,7 +2459,6 @@
break;
default:
/* Reserved R6 ops */
- pr_err("Reserved MIPS R6 CMP.condn.D operation\n");
return SIGILL;
}
}
diff --git a/arch/powerpc/perf/isa207-common.h b/arch/powerpc/perf/isa207-common.h
index 4d0a4e5..8e6dd17 100644
--- a/arch/powerpc/perf/isa207-common.h
+++ b/arch/powerpc/perf/isa207-common.h
@@ -201,6 +201,10 @@
CNST_PMC_VAL(1) | CNST_PMC_VAL(2) | CNST_PMC_VAL(3) | \
CNST_PMC_VAL(4) | CNST_PMC_VAL(5) | CNST_PMC_VAL(6) | CNST_NC_VAL
+/*
+ * Lets restrict use of PMC5 for instruction counting.
+ */
+#define P9_DD1_TEST_ADDER (ISA207_TEST_ADDER | CNST_PMC_VAL(5))
/* Bits in MMCR1 for PowerISA v2.07 */
#define MMCR1_UNIT_SHIFT(pmc) (60 - (4 * ((pmc) - 1)))
diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
index 8e9a819..9abcd8f 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -295,7 +295,7 @@
.name = "POWER9",
.n_counter = MAX_PMU_COUNTERS,
.add_fields = ISA207_ADD_FIELDS,
- .test_adder = ISA207_TEST_ADDER,
+ .test_adder = P9_DD1_TEST_ADDER,
.compute_mmcr = isa207_compute_mmcr,
.config_bhrb = power9_config_bhrb,
.bhrb_filter_map = power9_bhrb_filter_map,
diff --git a/arch/sparc/include/asm/setup.h b/arch/sparc/include/asm/setup.h
index be0cc1b..3fae200 100644
--- a/arch/sparc/include/asm/setup.h
+++ b/arch/sparc/include/asm/setup.h
@@ -59,8 +59,11 @@
extern atomic_t dcpage_flushes_xcall;
extern int sysctl_tsb_ratio;
-#endif
+#ifdef CONFIG_SERIAL_SUNHV
+void sunhv_migrate_hvcons_irq(int cpu);
+#endif
+#endif
void sun_do_break(void);
extern int stop_a_enabled;
extern int scons_pwroff;
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 2deb89e..ca7cb8e 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -1465,8 +1465,12 @@
int cpu;
if (tlb_type == hypervisor) {
+ int this_cpu = smp_processor_id();
+#ifdef CONFIG_SERIAL_SUNHV
+ sunhv_migrate_hvcons_irq(this_cpu);
+#endif
for_each_online_cpu(cpu) {
- if (cpu == smp_processor_id())
+ if (cpu == this_cpu)
continue;
#ifdef CONFIG_SUN_LDOMS
if (ldom_domaining_enabled) {
diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h
index e7636ba..6c98821 100644
--- a/arch/x86/include/asm/alternative-asm.h
+++ b/arch/x86/include/asm/alternative-asm.h
@@ -62,8 +62,10 @@
#define new_len2 145f-144f
/*
- * max without conditionals. Idea adapted from:
+ * gas compatible max based on the idea from:
* http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
+ *
+ * The additional "-" is needed because gas uses a "true" value of -1.
*/
#define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 1b02038..d4aea31 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -103,12 +103,12 @@
alt_end_marker ":\n"
/*
- * max without conditionals. Idea adapted from:
+ * gas compatible max based on the idea from:
* http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
*
- * The additional "-" is needed because gas works with s32s.
+ * The additional "-" is needed because gas uses a "true" value of -1.
*/
-#define alt_max_short(a, b) "((" a ") ^ (((" a ") ^ (" b ")) & -(-((" a ") - (" b ")))))"
+#define alt_max_short(a, b) "((" a ") ^ (((" a ") ^ (" b ")) & -(-((" a ") < (" b ")))))"
/*
* Pad the second replacement alternative with additional NOPs if it is
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 5f24127..d29c745 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3649,19 +3649,19 @@
unsigned level, unsigned gpte)
{
/*
- * PT_PAGE_TABLE_LEVEL always terminates. The RHS has bit 7 set
- * iff level <= PT_PAGE_TABLE_LEVEL, which for our purpose means
- * level == PT_PAGE_TABLE_LEVEL; set PT_PAGE_SIZE_MASK in gpte then.
- */
- gpte |= level - PT_PAGE_TABLE_LEVEL - 1;
-
- /*
* The RHS has bit 7 set iff level < mmu->last_nonleaf_level.
* If it is clear, there are no large pages at this level, so clear
* PT_PAGE_SIZE_MASK in gpte if that is the case.
*/
gpte &= level - mmu->last_nonleaf_level;
+ /*
+ * PT_PAGE_TABLE_LEVEL always terminates. The RHS has bit 7 set
+ * iff level <= PT_PAGE_TABLE_LEVEL, which for our purpose means
+ * level == PT_PAGE_TABLE_LEVEL; set PT_PAGE_SIZE_MASK in gpte then.
+ */
+ gpte |= level - PT_PAGE_TABLE_LEVEL - 1;
+
return gpte & PT_PAGE_SIZE_MASK;
}
@@ -4169,6 +4169,7 @@
update_permission_bitmask(vcpu, context, true);
update_pkru_bitmask(vcpu, context, true);
+ update_last_nonleaf_level(vcpu, context);
reset_rsvds_bits_mask_ept(vcpu, context, execonly);
reset_ept_shadow_zero_bits_mask(vcpu, context, execonly);
}
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index a011054..3736390 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -324,10 +324,11 @@
--walker->level;
index = PT_INDEX(addr, walker->level);
-
table_gfn = gpte_to_gfn(pte);
offset = index * sizeof(pt_element_t);
pte_gpa = gfn_to_gpa(table_gfn) + offset;
+
+ BUG_ON(walker->level < 1);
walker->table_gfn[walker->level - 1] = table_gfn;
walker->pte_gpa[walker->level - 1] = pte_gpa;
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index fb49212..a8ae57a 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -10690,7 +10690,7 @@
* (KVM doesn't change it)- no reason to call set_cr4_guest_host_mask();
*/
vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
- kvm_set_cr4(vcpu, vmcs12->host_cr4);
+ vmx_set_cr4(vcpu, vmcs12->host_cr4);
nested_ept_uninit_mmu_context(vcpu);
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 9a324fc..3e27ded 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -689,7 +689,7 @@
if (PageReserved(page)) {
__ClearPageReserved(page);
- magic = (unsigned long)page->lru.next;
+ magic = (unsigned long)page->freelist;
if (magic == SECTION_INFO || magic == MIX_SECTION_INFO) {
while (nr_pages--)
put_page_bootmem(page++);
diff --git a/block/bio.c b/block/bio.c
index 655c901..07f287b 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1171,8 +1171,8 @@
*/
bmd->is_our_pages = map_data ? 0 : 1;
memcpy(bmd->iov, iter->iov, sizeof(struct iovec) * iter->nr_segs);
- iov_iter_init(&bmd->iter, iter->type, bmd->iov,
- iter->nr_segs, iter->count);
+ bmd->iter = *iter;
+ bmd->iter.iov = bmd->iov;
ret = -ENOMEM;
bio = bio_kmalloc(gfp_mask, nr_pages);
@@ -1266,6 +1266,7 @@
int ret, offset;
struct iov_iter i;
struct iovec iov;
+ struct bio_vec *bvec;
iov_for_each(iov, i, *iter) {
unsigned long uaddr = (unsigned long) iov.iov_base;
@@ -1310,7 +1311,12 @@
ret = get_user_pages_fast(uaddr, local_nr_pages,
(iter->type & WRITE) != WRITE,
&pages[cur_page]);
- if (ret < local_nr_pages) {
+ if (unlikely(ret < local_nr_pages)) {
+ for (j = cur_page; j < page_limit; j++) {
+ if (!pages[j])
+ break;
+ put_page(pages[j]);
+ }
ret = -EFAULT;
goto out_unmap;
}
@@ -1318,6 +1324,7 @@
offset = offset_in_page(uaddr);
for (j = cur_page; j < page_limit; j++) {
unsigned int bytes = PAGE_SIZE - offset;
+ unsigned short prev_bi_vcnt = bio->bi_vcnt;
if (len <= 0)
break;
@@ -1332,6 +1339,13 @@
bytes)
break;
+ /*
+ * check if vector was merged with previous
+ * drop page reference if needed
+ */
+ if (bio->bi_vcnt == prev_bi_vcnt)
+ put_page(pages[j]);
+
len -= bytes;
offset = 0;
}
@@ -1364,10 +1378,8 @@
return bio;
out_unmap:
- for (j = 0; j < nr_pages; j++) {
- if (!pages[j])
- break;
- put_page(pages[j]);
+ bio_for_each_segment_all(bvec, bio, j) {
+ put_page(bvec->bv_page);
}
out:
kfree(pages);
diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index 341b8d8..650f427 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -147,6 +147,7 @@
failjob_rls_rqst_payload:
kfree(job->request_payload.sg_list);
failjob_rls_job:
+ kfree(job);
return -ENOMEM;
}
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 84d7148..fa98ad7 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -360,6 +360,7 @@
select CRYPTO_BLKCIPHER
select CRYPTO_MANAGER
select CRYPTO_GF128MUL
+ select CRYPTO_ECB
help
XTS: IEEE1619/D16 narrow block cipher use with aes-xts-plain,
key size 256, 384 or 512 bits. This implementation currently
diff --git a/crypto/shash.c b/crypto/shash.c
index a051541..4d8a671 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -274,12 +274,14 @@
int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc)
{
- struct scatterlist *sg = req->src;
- unsigned int offset = sg->offset;
unsigned int nbytes = req->nbytes;
+ struct scatterlist *sg;
+ unsigned int offset;
int err;
- if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) {
+ if (nbytes &&
+ (sg = req->src, offset = sg->offset,
+ nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) {
void *data;
data = kmap_atomic(sg_page(sg));
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 06f6668..7b313b5 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -20,6 +20,7 @@
#include <linux/phy.h>
struct property_set {
+ struct device *dev;
struct fwnode_handle fwnode;
struct property_entry *properties;
};
@@ -817,6 +818,7 @@
void device_remove_properties(struct device *dev)
{
struct fwnode_handle *fwnode;
+ struct property_set *pset;
fwnode = dev_fwnode(dev);
if (!fwnode)
@@ -826,16 +828,16 @@
* the pset. If there is no real firmware node (ACPI/DT) primary
* will hold the pset.
*/
- if (is_pset_node(fwnode)) {
+ pset = to_pset_node(fwnode);
+ if (pset) {
set_primary_fwnode(dev, NULL);
- pset_free_set(to_pset_node(fwnode));
} else {
- fwnode = fwnode->secondary;
- if (!IS_ERR(fwnode) && is_pset_node(fwnode)) {
+ pset = to_pset_node(fwnode->secondary);
+ if (pset && dev == pset->dev)
set_secondary_fwnode(dev, NULL);
- pset_free_set(to_pset_node(fwnode));
- }
}
+ if (pset && dev == pset->dev)
+ pset_free_set(pset);
}
EXPORT_SYMBOL_GPL(device_remove_properties);
@@ -863,6 +865,7 @@
p->fwnode.type = FWNODE_PDATA;
set_secondary_fwnode(dev, &p->fwnode);
+ p->dev = dev;
return 0;
}
EXPORT_SYMBOL_GPL(device_add_properties);
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index d02f2c1..c738bae 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -1682,8 +1682,12 @@
/* Disable platform specific wakeup interrupt */
if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) {
disable_irq_wake(card->plt_wake_cfg->irq_bt);
- if (!card->plt_wake_cfg->wake_by_bt)
- disable_irq(card->plt_wake_cfg->irq_bt);
+ disable_irq(card->plt_wake_cfg->irq_bt);
+ if (card->plt_wake_cfg->wake_by_bt)
+ /* Undo our disable, since interrupt handler already
+ * did this.
+ */
+ enable_irq(card->plt_wake_cfg->irq_bt);
}
return 0;
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index e2023bd..fd5984f 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -244,7 +244,7 @@
config ACPI_CPPC_CPUFREQ
tristate "CPUFreq driver based on the ACPI CPPC spec"
- depends on ACPI
+ depends on ACPI_PROCESSOR
select ACPI_CPPC_LIB
default n
help
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 77242b3..57962bf 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -1143,11 +1143,24 @@
struct edma_desc *edesc;
struct device *dev = chan->device->dev;
struct edma_chan *echan = to_edma_chan(chan);
- unsigned int width, pset_len;
+ unsigned int width, pset_len, array_size;
if (unlikely(!echan || !len))
return NULL;
+ /* Align the array size (acnt block) with the transfer properties */
+ switch (__ffs((src | dest | len))) {
+ case 0:
+ array_size = SZ_32K - 1;
+ break;
+ case 1:
+ array_size = SZ_32K - 2;
+ break;
+ default:
+ array_size = SZ_32K - 4;
+ break;
+ }
+
if (len < SZ_64K) {
/*
* Transfer size less than 64K can be handled with one paRAM
@@ -1169,7 +1182,7 @@
* When the full_length is multibple of 32767 one slot can be
* used to complete the transfer.
*/
- width = SZ_32K - 1;
+ width = array_size;
pset_len = rounddown(len, width);
/* One slot is enough for lengths multiple of (SZ_32K -1) */
if (unlikely(pset_len == len))
@@ -1217,7 +1230,7 @@
}
dest += pset_len;
src += pset_len;
- pset_len = width = len % (SZ_32K - 1);
+ pset_len = width = len % array_size;
ret = edma_config_pset(chan, &edesc->pset[1], src, dest, 1,
width, pset_len, DMA_MEM_TO_MEM);
diff --git a/drivers/dma/ti-dma-crossbar.c b/drivers/dma/ti-dma-crossbar.c
index 2403475..88a00d0 100644
--- a/drivers/dma/ti-dma-crossbar.c
+++ b/drivers/dma/ti-dma-crossbar.c
@@ -262,13 +262,14 @@
mutex_lock(&xbar->mutex);
map->xbar_out = find_first_zero_bit(xbar->dma_inuse,
xbar->dma_requests);
- mutex_unlock(&xbar->mutex);
if (map->xbar_out == xbar->dma_requests) {
+ mutex_unlock(&xbar->mutex);
dev_err(&pdev->dev, "Run out of free DMA requests\n");
kfree(map);
return ERR_PTR(-ENOMEM);
}
set_bit(map->xbar_out, xbar->dma_inuse);
+ mutex_unlock(&xbar->mutex);
map->xbar_in = (u16)dma_spec->args[0];
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index daaac2c..7db692e 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -981,20 +981,19 @@
pr_cont("]: 0x%016llx\n", m->status);
if (m->status & MCI_STATUS_ADDRV)
- pr_emerg(HW_ERR "Error Addr: 0x%016llx", m->addr);
+ pr_emerg(HW_ERR "Error Addr: 0x%016llx\n", m->addr);
if (boot_cpu_has(X86_FEATURE_SMCA)) {
+ pr_emerg(HW_ERR "IPID: 0x%016llx", m->ipid);
+
if (m->status & MCI_STATUS_SYNDV)
pr_cont(", Syndrome: 0x%016llx", m->synd);
- pr_cont(", IPID: 0x%016llx", m->ipid);
-
pr_cont("\n");
decode_smca_errors(m);
goto err_code;
- } else
- pr_cont("\n");
+ }
if (!fam_ops)
goto err_code;
diff --git a/drivers/esoc/esoc-mdm-4x.c b/drivers/esoc/esoc-mdm-4x.c
index 334278b..7eb0458 100644
--- a/drivers/esoc/esoc-mdm-4x.c
+++ b/drivers/esoc/esoc-mdm-4x.c
@@ -482,7 +482,7 @@
return IRQ_HANDLED;
}
-static int mdm_get_status(u32 *status, struct esoc_clink *esoc)
+static void mdm_get_status(u32 *status, struct esoc_clink *esoc)
{
struct mdm_ctrl *mdm = get_esoc_clink_data(esoc);
@@ -490,7 +490,16 @@
*status = 0;
else
*status = 1;
- return 0;
+}
+
+static void mdm_get_err_fatal(u32 *status, struct esoc_clink *esoc)
+{
+ struct mdm_ctrl *mdm = get_esoc_clink_data(esoc);
+
+ if (gpio_get_value(MDM_GPIO(mdm, MDM2AP_ERRFATAL)) == 0)
+ *status = 0;
+ else
+ *status = 1;
}
static void mdm_configure_debug(struct mdm_ctrl *mdm)
@@ -748,6 +757,7 @@
dev_err(mdm->dev, "cannot allocate esoc device\n");
return PTR_ERR(esoc);
}
+ esoc->pdev = pdev;
mdm->mdm_queue = alloc_workqueue("mdm_queue", 0, 0);
if (!mdm->mdm_queue) {
dev_err(mdm->dev, "could not create mdm_queue\n");
@@ -818,6 +828,7 @@
dev_err(mdm->dev, "cannot allocate esoc device\n");
return PTR_ERR(esoc);
}
+ esoc->pdev = pdev;
mdm->mdm_queue = alloc_workqueue("mdm_queue", 0, 0);
if (!mdm->mdm_queue) {
dev_err(mdm->dev, "could not create mdm_queue\n");
@@ -906,6 +917,7 @@
dev_err(mdm->dev, "cannot allocate esoc device\n");
return PTR_ERR(esoc);
}
+ esoc->pdev = pdev;
mdm->mdm_queue = alloc_workqueue("mdm_queue", 0, 0);
if (!mdm->mdm_queue) {
dev_err(mdm->dev, "could not create mdm_queue\n");
@@ -966,6 +978,7 @@
static struct esoc_clink_ops mdm_cops = {
.cmd_exe = mdm_cmd_exe,
.get_status = mdm_get_status,
+ .get_err_fatal = mdm_get_err_fatal,
.notify = mdm_notify,
};
diff --git a/drivers/esoc/esoc.h b/drivers/esoc/esoc.h
index 9fc3192..e6794c2 100644
--- a/drivers/esoc/esoc.h
+++ b/drivers/esoc/esoc.h
@@ -49,6 +49,7 @@
* @link_info: additional info about the physical link.
* @parent: parent device.
* @dev: device for userspace interface.
+ * @pdev: platform device to interface with SSR driver.
* @id: id of the external device.
* @owner: owner of the device.
* @clink_ops: control operations for the control link
@@ -66,6 +67,7 @@
const char *link_info;
struct device *parent;
struct device dev;
+ struct platform_device *pdev;
unsigned int id;
struct module *owner;
const struct esoc_clink_ops *clink_ops;
@@ -83,11 +85,13 @@
* struct esoc_clink_ops: Operations to control external soc
* @cmd_exe: Execute control command
* @get_status: Get current status, or response to previous command
+ * @get_err_fatal: Get status of err fatal signal
* @notify_esoc: notify external soc of events
*/
struct esoc_clink_ops {
int (*cmd_exe)(enum esoc_cmd cmd, struct esoc_clink *dev);
- int (*get_status)(u32 *status, struct esoc_clink *dev);
+ void (*get_status)(u32 *status, struct esoc_clink *dev);
+ void (*get_err_fatal)(u32 *status, struct esoc_clink *dev);
void (*notify)(enum esoc_notify notify, struct esoc_clink *dev);
};
diff --git a/drivers/esoc/esoc_bus.c b/drivers/esoc/esoc_bus.c
index cef570b..d9ab993 100644
--- a/drivers/esoc/esoc_bus.c
+++ b/drivers/esoc/esoc_bus.c
@@ -189,7 +189,7 @@
snprintf(subsys_name, len, "esoc%d", esoc_clink->id);
esoc_clink->subsys.name = subsys_name;
esoc_clink->dev.of_node = esoc_clink->np;
- esoc_clink->subsys.dev = &esoc_clink->dev;
+ esoc_clink->subsys.dev = &esoc_clink->pdev->dev;
esoc_clink->subsys_dev = subsys_register(&esoc_clink->subsys);
if (IS_ERR_OR_NULL(esoc_clink->subsys_dev)) {
dev_err(&esoc_clink->dev, "failed to register ssr node\n");
diff --git a/drivers/esoc/esoc_dev.c b/drivers/esoc/esoc_dev.c
index 0c9e428..1d9e623 100644
--- a/drivers/esoc/esoc_dev.c
+++ b/drivers/esoc/esoc_dev.c
@@ -224,9 +224,11 @@
clink_ops->notify(esoc_cmd, esoc_clink);
break;
case ESOC_GET_STATUS:
- err = clink_ops->get_status(&status, esoc_clink);
- if (err)
- return err;
+ clink_ops->get_status(&status, esoc_clink);
+ put_user(status, (unsigned int __user *)uarg);
+ break;
+ case ESOC_GET_ERR_FATAL:
+ clink_ops->get_err_fatal(&status, esoc_clink);
put_user(status, (unsigned int __user *)uarg);
break;
case ESOC_WAIT_FOR_CRASH:
@@ -336,7 +338,6 @@
esoc_udev = esoc_udev_get_by_minor(esoc_clink->id);
if (!esoc_udev)
return 0;
- return_esoc_udev(esoc_udev);
device_destroy(esoc_class, MKDEV(esoc_major, esoc_clink->id));
return_esoc_udev(esoc_udev);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 264899d..05ff98b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -491,6 +491,9 @@
case TTM_PL_TT:
break;
case TTM_PL_VRAM:
+ if (mem->start == AMDGPU_BO_INVALID_OFFSET)
+ return -EINVAL;
+
mem->bus.offset = mem->start << PAGE_SHIFT;
/* check if it's visible */
if ((mem->bus.offset + mem->bus.size) > adev->mc.visible_vram_size)
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 8aeb7f8..80c5cc5 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -1219,7 +1219,7 @@
{
enum port port;
- if (!HAS_DDI(dev_priv))
+ if (!HAS_DDI(dev_priv) && !IS_CHERRYVIEW(dev_priv))
return;
if (!dev_priv->vbt.child_dev_num)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f8efd20..ce32303 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11471,13 +11471,10 @@
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
+ enum transcoder cpu_transcoder;
struct drm_display_mode *mode;
struct intel_crtc_state *pipe_config;
- int htot = I915_READ(HTOTAL(cpu_transcoder));
- int hsync = I915_READ(HSYNC(cpu_transcoder));
- int vtot = I915_READ(VTOTAL(cpu_transcoder));
- int vsync = I915_READ(VSYNC(cpu_transcoder));
+ u32 htot, hsync, vtot, vsync;
enum pipe pipe = intel_crtc->pipe;
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
@@ -11505,6 +11502,13 @@
i9xx_crtc_clock_get(intel_crtc, pipe_config);
mode->clock = pipe_config->port_clock / pipe_config->pixel_multiplier;
+
+ cpu_transcoder = pipe_config->cpu_transcoder;
+ htot = I915_READ(HTOTAL(cpu_transcoder));
+ hsync = I915_READ(HSYNC(cpu_transcoder));
+ vtot = I915_READ(VTOTAL(cpu_transcoder));
+ vsync = I915_READ(VSYNC(cpu_transcoder));
+
mode->hdisplay = (htot & 0xffff) + 1;
mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
mode->hsync_start = (hsync & 0xffff) + 1;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 7b06280..afa3d01 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2193,8 +2193,8 @@
I915_WRITE(pp_ctrl_reg, pp);
POSTING_READ(pp_ctrl_reg);
- intel_dp->panel_power_off_time = ktime_get_boottime();
wait_panel_off(intel_dp);
+ intel_dp->panel_power_off_time = ktime_get_boottime();
/* We got a reference when we enabled the VDD. */
power_domain = intel_display_port_aux_power_domain(intel_encoder);
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 7d1e4bf..8855859 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -3044,18 +3044,18 @@
nsecs_to_jiffies(ktime_to_ns(wakeup_time)));
}
-void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
+int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
struct sde_encoder_kickoff_params *params)
{
struct sde_encoder_virt *sde_enc;
struct sde_encoder_phys *phys;
bool needs_hw_reset = false;
unsigned int i;
- int rc;
+ int rc, ret = 0;
if (!drm_enc || !params) {
SDE_ERROR("invalid args\n");
- return;
+ return -EINVAL;
}
sde_enc = to_sde_encoder_virt(drm_enc);
@@ -3067,8 +3067,12 @@
for (i = 0; i < sde_enc->num_phys_encs; i++) {
phys = sde_enc->phys_encs[i];
if (phys) {
- if (phys->ops.prepare_for_kickoff)
- phys->ops.prepare_for_kickoff(phys, params);
+ if (phys->ops.prepare_for_kickoff) {
+ rc = phys->ops.prepare_for_kickoff(
+ phys, params);
+ if (rc)
+ ret = rc;
+ }
if (phys->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET)
needs_hw_reset = true;
_sde_encoder_setup_dither(phys);
@@ -3094,17 +3098,23 @@
if (sde_enc->cur_master && sde_enc->cur_master->connector) {
rc = sde_connector_pre_kickoff(sde_enc->cur_master->connector);
- if (rc)
+ if (rc) {
SDE_ERROR_ENC(sde_enc, "kickoff conn%d failed rc %d\n",
sde_enc->cur_master->connector->base.id,
rc);
+ ret = rc;
+ }
}
if (sde_encoder_is_dsc_enabled(drm_enc)) {
rc = _sde_encoder_dsc_setup(sde_enc, params);
- if (rc)
+ if (rc) {
SDE_ERROR_ENC(sde_enc, "failed to setup DSC: %d\n", rc);
+ ret = rc;
+ }
}
+
+ return ret;
}
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h
index 9a9ff86..40d3903 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.h
@@ -115,8 +115,9 @@
* Delayed: Block until next trigger can be issued.
* @encoder: encoder pointer
* @params: kickoff time parameters
+ * @Returns: Zero on success, last detected error otherwise
*/
-void sde_encoder_prepare_for_kickoff(struct drm_encoder *encoder,
+int sde_encoder_prepare_for_kickoff(struct drm_encoder *encoder,
struct sde_encoder_kickoff_params *params);
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index e5a4da4..0777e9c 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -160,7 +160,7 @@
int (*wait_for_commit_done)(struct sde_encoder_phys *phys_enc);
int (*wait_for_tx_complete)(struct sde_encoder_phys *phys_enc);
int (*wait_for_vblank)(struct sde_encoder_phys *phys_enc);
- void (*prepare_for_kickoff)(struct sde_encoder_phys *phys_enc,
+ int (*prepare_for_kickoff)(struct sde_encoder_phys *phys_enc,
struct sde_encoder_kickoff_params *params);
void (*handle_post_kickoff)(struct sde_encoder_phys *phys_enc);
void (*trigger_flush)(struct sde_encoder_phys *phys_enc);
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 9976f85..cb73904 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -984,7 +984,7 @@
hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_CMD;
}
-static void sde_encoder_phys_cmd_prepare_for_kickoff(
+static int sde_encoder_phys_cmd_prepare_for_kickoff(
struct sde_encoder_phys *phys_enc,
struct sde_encoder_kickoff_params *params)
{
@@ -994,7 +994,7 @@
if (!phys_enc || !phys_enc->hw_pp) {
SDE_ERROR("invalid encoder\n");
- return;
+ return -EINVAL;
}
SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
@@ -1018,6 +1018,7 @@
SDE_DEBUG_CMDENC(cmd_enc, "pp:%d pending_cnt %d\n",
phys_enc->hw_pp->idx - PINGPONG_0,
atomic_read(&phys_enc->pending_kickoff_cnt));
+ return ret;
}
static int _sde_encoder_phys_cmd_wait_for_ctl_start(
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 a983b7c..8076319 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -763,7 +763,7 @@
return _sde_encoder_phys_vid_wait_for_vblank(phys_enc, true);
}
-static void sde_encoder_phys_vid_prepare_for_kickoff(
+static int sde_encoder_phys_vid_prepare_for_kickoff(
struct sde_encoder_phys *phys_enc,
struct sde_encoder_kickoff_params *params)
{
@@ -771,15 +771,15 @@
struct sde_hw_ctl *ctl;
int rc;
- if (!phys_enc || !params) {
+ if (!phys_enc || !params || !phys_enc->hw_ctl) {
SDE_ERROR("invalid encoder/parameters\n");
- return;
+ return -EINVAL;
}
vid_enc = to_sde_encoder_phys_vid(phys_enc);
ctl = phys_enc->hw_ctl;
- if (!ctl || !ctl->ops.wait_reset_status)
- return;
+ if (!ctl->ops.wait_reset_status)
+ return 0;
/*
* hw supports hardware initiated ctl reset, so before we kickoff a new
@@ -794,6 +794,8 @@
}
programmable_rot_fetch_config(phys_enc, params->inline_rotate_prefill);
+
+ return rc;
}
static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc)
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
index d7084dd..bf7d3da 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
@@ -925,8 +925,9 @@
* sde_encoder_phys_wb_prepare_for_kickoff - pre-kickoff processing
* @phys_enc: Pointer to physical encoder
* @params: kickoff parameters
+ * Returns: Zero on success
*/
-static void sde_encoder_phys_wb_prepare_for_kickoff(
+static int sde_encoder_phys_wb_prepare_for_kickoff(
struct sde_encoder_phys *phys_enc,
struct sde_encoder_kickoff_params *params)
{
@@ -941,7 +942,7 @@
ret = sde_encoder_phys_wb_register_irq(phys_enc);
if (ret) {
SDE_ERROR("failed to register irq %d\n", ret);
- return;
+ return ret;
}
wb_enc->kickoff_count++;
@@ -955,6 +956,7 @@
wb_enc->start_time = ktime_get();
SDE_EVT32(DRMID(phys_enc->parent), WBID(wb_enc), wb_enc->kickoff_count);
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_rot.c b/drivers/gpu/drm/msm/sde/sde_hw_rot.c
index c5af3a9..8d386a8 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_rot.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_rot.c
@@ -588,6 +588,10 @@
cmd_type = SDE_ROTATOR_INLINE_CMD_CLEANUP;
priv_handle = data->priv_handle;
break;
+ case SDE_HW_ROT_CMD_RESET:
+ cmd_type = SDE_ROTATOR_INLINE_CMD_ABORT;
+ priv_handle = data->priv_handle;
+ break;
default:
SDE_ERROR("invalid hw rotator command %d\n", hw_cmd);
return -EINVAL;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_rot.h b/drivers/gpu/drm/msm/sde/sde_hw_rot.h
index 1237858..ea88d05 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_rot.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_rot.h
@@ -28,12 +28,14 @@
* @SDE_HW_ROT_CMD_COMMIT: commit/execute rotator command
* @SDE_HW_ROT_CMD_START: mdp is ready to start
* @SDE_HW_ROT_CMD_CLEANUP: cleanup rotator command after it is done
+ * @SDE_HW_ROT_CMD_RESET: request rotator h/w reset
*/
enum sde_hw_rot_cmd_type {
SDE_HW_ROT_CMD_VALIDATE,
SDE_HW_ROT_CMD_COMMIT,
SDE_HW_ROT_CMD_START,
SDE_HW_ROT_CMD_CLEANUP,
+ SDE_HW_ROT_CMD_RESET,
};
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 10e52bf..8aab213 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -103,6 +103,7 @@
* @sbuf_mode: force stream buffer mode if set
* @sbuf_writeback: force stream buffer writeback if set
* @revalidate: force revalidation of all the plane properties
+ * @xin_halt_forced_clk: whether or not clocks were forced on for xin halt
* @blob_rot_caps: Pointer to rotator capability blob
*/
struct sde_plane {
@@ -128,6 +129,7 @@
u32 sbuf_mode;
u32 sbuf_writeback;
bool revalidate;
+ bool xin_halt_forced_clk;
struct sde_csc_cfg csc_cfg;
struct sde_csc_cfg *csc_usr_ptr;
@@ -2489,6 +2491,111 @@
msm_framebuffer_cleanup(state->fb, pstate->aspace);
}
+static bool _sde_plane_halt_requests(struct drm_plane *plane,
+ uint32_t xin_id, bool halt_forced_clk, bool enable)
+{
+ struct sde_plane *psde;
+ struct msm_drm_private *priv;
+ struct sde_vbif_set_xin_halt_params halt_params;
+
+ if (!plane || !plane->dev) {
+ SDE_ERROR("invalid arguments\n");
+ return false;
+ }
+
+ psde = to_sde_plane(plane);
+ if (!psde->pipe_hw || !psde->pipe_hw->cap) {
+ SDE_ERROR("invalid pipe reference\n");
+ return false;
+ }
+
+ priv = plane->dev->dev_private;
+ if (!priv || !priv->kms) {
+ SDE_ERROR("invalid KMS reference\n");
+ return false;
+ }
+
+ memset(&halt_params, 0, sizeof(halt_params));
+ halt_params.vbif_idx = VBIF_RT;
+ halt_params.xin_id = xin_id;
+ halt_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
+ halt_params.forced_on = halt_forced_clk;
+ halt_params.enable = enable;
+
+ return sde_vbif_set_xin_halt(to_sde_kms(priv->kms), &halt_params);
+}
+
+void sde_plane_halt_requests(struct drm_plane *plane, bool enable)
+{
+ struct sde_plane *psde;
+
+ if (!plane) {
+ SDE_ERROR("invalid plane\n");
+ return;
+ }
+
+ psde = to_sde_plane(plane);
+ if (!psde->pipe_hw || !psde->pipe_hw->cap) {
+ SDE_ERROR("invalid pipe reference\n");
+ return;
+ }
+
+ SDE_EVT32(DRMID(plane), psde->xin_halt_forced_clk, enable);
+
+ psde->xin_halt_forced_clk =
+ _sde_plane_halt_requests(plane, psde->pipe_hw->cap->xin_id,
+ psde->xin_halt_forced_clk, enable);
+}
+
+int sde_plane_reset_rot(struct drm_plane *plane, struct drm_plane_state *state)
+{
+ struct sde_plane *psde;
+ struct sde_plane_state *pstate;
+ struct sde_plane_rot_state *rstate;
+ bool halt_ret[MAX_BLOCKS] = {false};
+ signed int i, count;
+
+ if (!plane || !state) {
+ SDE_ERROR("invalid plane\n");
+ return -EINVAL;
+ }
+
+ psde = to_sde_plane(plane);
+ pstate = to_sde_plane_state(state);
+ rstate = &pstate->rot;
+
+ /* do nothing if not master rotator plane */
+ if (!rstate->out_sbuf || !rstate->rot_hw ||
+ !rstate->rot_hw->caps || (rstate->out_xpos != 0))
+ return 0;
+
+ count = (signed int)rstate->rot_hw->caps->xin_count;
+ if (count > ARRAY_SIZE(halt_ret))
+ count = ARRAY_SIZE(halt_ret);
+
+ SDE_DEBUG_PLANE(psde, "issuing reset for rotator\n");
+ SDE_EVT32(DRMID(plane), count);
+
+ for (i = 0; i < count; i++) {
+ const struct sde_rot_vbif_cfg *cfg =
+ &rstate->rot_hw->caps->vbif_cfg[i];
+
+ halt_ret[i] = _sde_plane_halt_requests(plane, cfg->xin_id,
+ false, true);
+ }
+
+ sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_RESET);
+
+ for (i = count - 1; i >= 0; --i) {
+ const struct sde_rot_vbif_cfg *cfg =
+ &rstate->rot_hw->caps->vbif_cfg[i];
+
+ _sde_plane_halt_requests(plane, cfg->xin_id,
+ halt_ret[i], false);
+ }
+ return 0;
+}
+
int sde_plane_kickoff_rot(struct drm_plane *plane)
{
struct sde_plane_state *pstate;
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h
index e1b07c2..5c1fff1 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.h
+++ b/drivers/gpu/drm/msm/sde/sde_plane.h
@@ -228,6 +228,23 @@
void sde_plane_flush(struct drm_plane *plane);
/**
+ * sde_plane_halt_requests - control halting of vbif transactions for this plane
+ * This function isn't thread safe. Plane halt enable/disable requests
+ * should always be made from the same commit cycle.
+ * @plane: Pointer to drm plane structure
+ * @enable: Whether to enable/disable halting of vbif transactions
+ */
+void sde_plane_halt_requests(struct drm_plane *plane, bool enable);
+
+/**
+ * sde_plane_reset_rot - reset rotator operations before commit kickoff
+ * @plane: Pointer to drm plane structure
+ * @state: Pointer to plane state associated with reset request
+ * Returns: Zero on success
+ */
+int sde_plane_reset_rot(struct drm_plane *plane, struct drm_plane_state *state);
+
+/**
* sde_plane_kickoff_rot - final plane rotator operations before commit kickoff
* @plane: Pointer to drm plane structure
* Returns: Zero on success
diff --git a/drivers/gpu/drm/msm/sde/sde_vbif.c b/drivers/gpu/drm/msm/sde/sde_vbif.c
index 2cdc2f3..522f7f9 100644
--- a/drivers/gpu/drm/msm/sde/sde_vbif.c
+++ b/drivers/gpu/drm/msm/sde/sde_vbif.c
@@ -230,13 +230,15 @@
for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) {
if (sde_kms->hw_vbif[i] &&
- sde_kms->hw_vbif[i]->idx == params->vbif_idx)
+ sde_kms->hw_vbif[i]->idx == params->vbif_idx) {
vbif = sde_kms->hw_vbif[i];
+ break;
+ }
}
if (!vbif || !mdp) {
SDE_DEBUG("invalid arguments vbif %d mdp %d\n",
- vbif != 0, mdp != 0);
+ vbif != NULL, mdp != NULL);
return;
}
@@ -275,6 +277,58 @@
return;
}
+bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
+ struct sde_vbif_set_xin_halt_params *params)
+{
+ struct sde_hw_vbif *vbif = NULL;
+ struct sde_hw_mdp *mdp;
+ bool forced_on = false;
+ int ret, i;
+
+ if (!sde_kms || !params) {
+ SDE_ERROR("invalid arguments\n");
+ return false;
+ }
+ mdp = sde_kms->hw_mdp;
+
+ for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) {
+ if (sde_kms->hw_vbif[i] &&
+ sde_kms->hw_vbif[i]->idx == params->vbif_idx) {
+ vbif = sde_kms->hw_vbif[i];
+ break;
+ }
+ }
+
+ if (!vbif || !mdp) {
+ SDE_DEBUG("invalid arguments vbif %d mdp %d\n",
+ vbif != NULL, mdp != NULL);
+ return false;
+ }
+
+ if (!mdp->ops.setup_clk_force_ctrl ||
+ !vbif->ops.set_halt_ctrl)
+ return false;
+
+ if (params->enable) {
+ forced_on = mdp->ops.setup_clk_force_ctrl(mdp,
+ params->clk_ctrl, true);
+
+ vbif->ops.set_halt_ctrl(vbif, params->xin_id, true);
+
+ ret = _sde_vbif_wait_for_xin_halt(vbif, params->xin_id);
+ if (ret)
+ SDE_EVT32(vbif->idx, params->xin_id, SDE_EVTLOG_ERROR);
+ } else {
+ vbif->ops.set_halt_ctrl(vbif, params->xin_id, false);
+
+ if (params->forced_on)
+ mdp->ops.setup_clk_force_ctrl(mdp,
+ params->clk_ctrl, false);
+ }
+
+ return forced_on;
+}
+
void sde_vbif_set_qos_remap(struct sde_kms *sde_kms,
struct sde_vbif_set_qos_params *params)
{
diff --git a/drivers/gpu/drm/msm/sde/sde_vbif.h b/drivers/gpu/drm/msm/sde/sde_vbif.h
index 30cc416..0edc1a6 100644
--- a/drivers/gpu/drm/msm/sde/sde_vbif.h
+++ b/drivers/gpu/drm/msm/sde/sde_vbif.h
@@ -35,6 +35,23 @@
};
/**
+ * struct sde_vbif_set_xin_halt_params - xin halt parameters
+ * @vbif_idx: vbif identifier
+ * @xin_id: client interface identifier
+ * @clk_ctrl: clock control identifier of the xin
+ * @forced_on: whether or not previous call to xin halt forced the clocks on,
+ * only applicable to xin halt disable calls
+ * @enable: whether to enable/disable xin halts
+ */
+struct sde_vbif_set_xin_halt_params {
+ u32 vbif_idx;
+ u32 xin_id;
+ u32 clk_ctrl;
+ bool forced_on;
+ bool enable;
+};
+
+/**
* struct sde_vbif_set_qos_params - QoS remapper parameter
* @vbif_idx: vbif identifier
* @xin_id: client interface identifier
@@ -59,6 +76,16 @@
struct sde_vbif_set_ot_params *params);
/**
+ * sde_vbif_set_xin_halt - halt one of the xin ports
+ * This function isn't thread safe.
+ * @sde_kms: SDE handler
+ * @params: Pointer to halt configuration parameters
+ * Returns: Whether or not VBIF clocks were forced on
+ */
+bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
+ struct sde_vbif_set_xin_halt_params *params);
+
+/**
* sde_vbif_set_qos_remap - set QoS priority level remap
* @sde_kms: SDE handler
* @params: Pointer to QoS configuration parameters
diff --git a/drivers/gpu/drm/msm/sde_power_handle.h b/drivers/gpu/drm/msm/sde_power_handle.h
index 18777fd..6e00184 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.h
+++ b/drivers/gpu/drm/msm/sde_power_handle.h
@@ -18,7 +18,7 @@
#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA 0
#define SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA 0
-#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 1600000000
+#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 400000000
#define SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA 0
#include <linux/sde_io_util.h>
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index 6584d50..133f896 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -1129,7 +1129,7 @@
if (trap & 0x00000008) {
u32 stat = nvkm_rd32(device, 0x408030);
- nvkm_snprintbf(error, sizeof(error), gf100_m2mf_error,
+ nvkm_snprintbf(error, sizeof(error), gf100_ccache_error,
stat & 0x3fffffff);
nvkm_error(subdev, "CCACHE %08x [%s]\n", stat, error);
nvkm_wr32(device, 0x408030, 0xc0000000);
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 8cbc75e..92f51bc 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -73,14 +73,14 @@
{A6XX_RBBM_CLOCK_CNTL2_SP1, 0x02022220},
{A6XX_RBBM_CLOCK_CNTL2_SP2, 0x02022220},
{A6XX_RBBM_CLOCK_CNTL2_SP3, 0x02022220},
- {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_DELAY_SP0, 0x00000080},
+ {A6XX_RBBM_CLOCK_DELAY_SP1, 0x00000080},
+ {A6XX_RBBM_CLOCK_DELAY_SP2, 0x00000080},
+ {A6XX_RBBM_CLOCK_DELAY_SP3, 0x00000080},
+ {A6XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
+ {A6XX_RBBM_CLOCK_HYST_SP1, 0x0000F3CF},
+ {A6XX_RBBM_CLOCK_HYST_SP2, 0x0000F3CF},
+ {A6XX_RBBM_CLOCK_HYST_SP3, 0x0000F3CF},
{A6XX_RBBM_CLOCK_CNTL_TP0, 0x02222222},
{A6XX_RBBM_CLOCK_CNTL_TP1, 0x02222222},
{A6XX_RBBM_CLOCK_CNTL_TP2, 0x02222222},
@@ -105,10 +105,10 @@
{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_HYST3_TP0, 0x77777777},
+ {A6XX_RBBM_CLOCK_HYST3_TP1, 0x77777777},
+ {A6XX_RBBM_CLOCK_HYST3_TP2, 0x77777777},
+ {A6XX_RBBM_CLOCK_HYST3_TP3, 0x77777777},
{A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
{A6XX_RBBM_CLOCK_HYST4_TP1, 0x00077777},
{A6XX_RBBM_CLOCK_HYST4_TP2, 0x00077777},
@@ -143,20 +143,20 @@
{A6XX_RBBM_CLOCK_CNTL2_RB1, 0x00002222},
{A6XX_RBBM_CLOCK_CNTL2_RB2, 0x00002222},
{A6XX_RBBM_CLOCK_CNTL2_RB3, 0x00002222},
- {A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00000000},
- {A6XX_RBBM_CLOCK_CNTL_CCU1, 0x00000000},
- {A6XX_RBBM_CLOCK_CNTL_CCU2, 0x00000000},
- {A6XX_RBBM_CLOCK_CNTL_CCU3, 0x00000000},
+ {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, 0x00022022},
- {A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005550},
- {A6XX_RBBM_CLOCK_DELAY_RAC, 0x00010011},
+ {A6XX_RBBM_CLOCK_CNTL_RAC, 0x05022022},
+ {A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+ {A6XX_RBBM_CLOCK_DELAY_RAC, 0x00000011},
{A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
- {A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222220},
- {A6XX_RBBM_CLOCK_MODE_GPC, 0x00202222},
+ {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},
@@ -765,7 +765,7 @@
*cmds++ = lower_32_bits(gpuaddr);
*cmds++ = upper_32_bits(gpuaddr);
/* Size is in dwords */
- *cmds++ = 0;
+ *cmds++ = sizeof(a6xx_pwrup_reglist) >> 2;
}
/* Pad rest of the cmds with 0's */
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index ae83af6..7838343 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -971,6 +971,8 @@
unsigned int rsize = 0;
char *rdesc;
int ret, n;
+ int num_descriptors;
+ size_t offset = offsetof(struct hid_descriptor, desc);
quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
@@ -993,10 +995,18 @@
return -ENODEV;
}
+ if (hdesc->bLength < sizeof(struct hid_descriptor)) {
+ dbg_hid("hid descriptor is too short\n");
+ return -EINVAL;
+ }
+
hid->version = le16_to_cpu(hdesc->bcdHID);
hid->country = hdesc->bCountryCode;
- for (n = 0; n < hdesc->bNumDescriptors; n++)
+ num_descriptors = min_t(int, hdesc->bNumDescriptors,
+ (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor));
+
+ for (n = 0; n < num_descriptors; n++)
if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 04ebd03..16a3e7d 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -777,7 +777,8 @@
adc_chan_result->measurement = pmic_voltage*
chan_properties->offset_gain_denominator;
- do_div(adc_chan_result->measurement,
+ adc_chan_result->measurement =
+ div64_s64(adc_chan_result->measurement,
chan_properties->offset_gain_numerator * 2);
} else
adc_chan_result->measurement = 0;
@@ -805,9 +806,11 @@
if (param->adc_tm_hc) {
low_output *= param->full_scale_code;
- do_div(low_output, (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
+ low_output = div64_s64(low_output,
+ (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
high_output *= param->full_scale_code;
- do_div(high_output, (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
+ high_output = div64_s64(high_output,
+ (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
} else {
rc = qpnp_get_vadc_gain_and_offset(chip, &btm_param,
CALIB_ABSOLUTE);
@@ -822,7 +825,7 @@
sign = 1;
low_output = -low_output;
}
- do_div(low_output, QPNP_ADC_625_UV);
+ low_output = div64_s64(low_output, QPNP_ADC_625_UV);
if (sign)
low_output = -low_output;
low_output += btm_param.adc_gnd;
@@ -834,7 +837,7 @@
sign = 1;
high_output = -high_output;
}
- do_div(high_output, QPNP_ADC_625_UV);
+ high_output = div64_s64(high_output, QPNP_ADC_625_UV);
if (sign)
high_output = -high_output;
high_output += btm_param.adc_gnd;
@@ -885,7 +888,7 @@
adc_properties, chan_properties, &xo_thm_voltage);
if (chan_properties->calib_type == CALIB_ABSOLUTE)
- do_div(xo_thm_voltage, 1000);
+ xo_thm_voltage = div64_s64(xo_thm_voltage, 1000);
qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
ARRAY_SIZE(adcmap_100k_104ef_104fb),
@@ -1085,7 +1088,7 @@
adc_properties, chan_properties, &therm_voltage);
if (chan_properties->calib_type == CALIB_ABSOLUTE)
- do_div(therm_voltage, 1000);
+ therm_voltage = div64_s64(therm_voltage, 1000);
qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
ARRAY_SIZE(adcmap_100k_104ef_104fb),
@@ -1124,7 +1127,7 @@
adc_voltage = -adc_voltage;
}
- do_div(adc_voltage, param1.dy);
+ adc_voltage = div64_s64(adc_voltage, param1.dy);
qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
ARRAY_SIZE(adcmap_100k_104ef_104fb),
@@ -1152,7 +1155,8 @@
if (rc)
return rc;
param->low_thr_voltage *= adc_properties->full_scale_code;
- do_div(param->low_thr_voltage, QPNP_VADC_HC_VDD_REFERENCE_MV);
+ param->low_thr_voltage = div64_s64(param->low_thr_voltage,
+ QPNP_VADC_HC_VDD_REFERENCE_MV);
rc = qpnp_adc_map_temp_voltage(
adcmap_100k_104ef_104fb_1875_vref,
@@ -1161,7 +1165,8 @@
if (rc)
return rc;
param->high_thr_voltage *= adc_properties->full_scale_code;
- do_div(param->high_thr_voltage, QPNP_VADC_HC_VDD_REFERENCE_MV);
+ param->high_thr_voltage = div64_s64(param->high_thr_voltage,
+ QPNP_VADC_HC_VDD_REFERENCE_MV);
} else {
qpnp_get_vadc_gain_and_offset(chip, ¶m1, CALIB_RATIOMETRIC);
@@ -1172,7 +1177,8 @@
return rc;
param->low_thr_voltage *= param1.dy;
- do_div(param->low_thr_voltage, param1.adc_vref);
+ param->low_thr_voltage = div64_s64(param->low_thr_voltage,
+ param1.adc_vref);
param->low_thr_voltage += param1.adc_gnd;
rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
@@ -1182,7 +1188,8 @@
return rc;
param->high_thr_voltage *= param1.dy;
- do_div(param->high_thr_voltage, param1.adc_vref);
+ param->high_thr_voltage = div64_s64(param->high_thr_voltage,
+ param1.adc_vref);
param->high_thr_voltage += param1.adc_gnd;
}
@@ -1281,11 +1288,11 @@
qpnp_get_vadc_gain_and_offset(chip, &usb_param, CALIB_RATIOMETRIC);
*low_threshold = param->low_thr * usb_param.dy;
- do_div(*low_threshold, usb_param.adc_vref);
+ *low_threshold = div64_s64(*low_threshold, usb_param.adc_vref);
*low_threshold += usb_param.adc_gnd;
*high_threshold = param->high_thr * usb_param.dy;
- do_div(*high_threshold, usb_param.adc_vref);
+ *high_threshold = div64_s64(*high_threshold, usb_param.adc_vref);
*high_threshold += usb_param.adc_gnd;
pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
@@ -1306,13 +1313,15 @@
low_thr = (param->low_thr/param->gain_den);
low_thr *= param->gain_num;
low_thr *= param->full_scale_code;
- do_div(low_thr, (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
+ low_thr = div64_s64(low_thr,
+ (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
*low_threshold = low_thr;
high_thr = (param->high_thr/param->gain_den);
high_thr *= param->gain_num;
high_thr *= param->full_scale_code;
- do_div(high_thr, (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
+ high_thr = div64_s64(high_thr,
+ (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
*high_threshold = high_thr;
} else {
rc = qpnp_get_vadc_gain_and_offset(chip, &vbatt_param,
@@ -1327,7 +1336,7 @@
low_thr = -low_thr;
}
low_thr = low_thr * param->gain_num;
- do_div(low_thr, QPNP_ADC_625_UV);
+ low_thr = div64_s64(low_thr, QPNP_ADC_625_UV);
if (sign)
low_thr = -low_thr;
*low_threshold = low_thr + vbatt_param.adc_gnd;
@@ -1340,7 +1349,7 @@
high_thr = -high_thr;
}
high_thr = high_thr * param->gain_num;
- do_div(high_thr, QPNP_ADC_625_UV);
+ high_thr = div64_s64(high_thr, QPNP_ADC_625_UV);
if (sign)
high_thr = -high_thr;
*high_threshold = high_thr + vbatt_param.adc_gnd;
@@ -1387,7 +1396,7 @@
low_thr = -low_thr;
}
low_thr = low_thr * chan_prop->offset_gain_numerator;
- do_div(low_thr, QPNP_ADC_625_UV);
+ low_thr = div64_s64(low_thr, QPNP_ADC_625_UV);
if (sign)
low_thr = -low_thr;
*low_threshold = low_thr + vbatt_param.adc_gnd;
@@ -1400,7 +1409,7 @@
high_thr = -high_thr;
}
high_thr = high_thr * chan_prop->offset_gain_numerator;
- do_div(high_thr, QPNP_ADC_625_UV);
+ high_thr = div64_s64(high_thr, QPNP_ADC_625_UV);
if (sign)
high_thr = -high_thr;
*high_threshold = high_thr + vbatt_param.adc_gnd;
@@ -1442,7 +1451,7 @@
pr_debug("low_output:%lld\n", low_output);
low_output *= btm_param.dy;
- do_div(low_output, btm_param.adc_vref);
+ low_output = div64_s64(low_output, btm_param.adc_vref);
low_output += btm_param.adc_gnd;
rc = qpnp_adc_map_voltage_temp(
@@ -1457,7 +1466,7 @@
pr_debug("high_output:%lld\n", high_output);
high_output *= btm_param.dy;
- do_div(high_output, btm_param.adc_vref);
+ high_output = div64_s64(high_output, btm_param.adc_vref);
high_output += btm_param.adc_gnd;
/* btm low temperature correspondes to high voltage threshold */
@@ -1500,7 +1509,7 @@
pr_debug("low_output:%lld\n", low_output);
low_output *= btm_param.dy;
- do_div(low_output, btm_param.adc_vref);
+ low_output = div64_s64(low_output, btm_param.adc_vref);
low_output += btm_param.adc_gnd;
rc = qpnp_adc_map_voltage_temp(
@@ -1515,7 +1524,7 @@
pr_debug("high_output:%lld\n", high_output);
high_output *= btm_param.dy;
- do_div(high_output, btm_param.adc_vref);
+ high_output = div64_s64(high_output, btm_param.adc_vref);
high_output += btm_param.adc_gnd;
/* btm low temperature correspondes to high voltage threshold */
@@ -1558,7 +1567,7 @@
pr_debug("low_output:%lld\n", low_output);
low_output *= btm_param.dy;
- do_div(low_output, btm_param.adc_vref);
+ low_output = div64_s64(low_output, btm_param.adc_vref);
low_output += btm_param.adc_gnd;
rc = qpnp_adc_map_voltage_temp(
@@ -1573,7 +1582,7 @@
pr_debug("high_output:%lld\n", high_output);
high_output *= btm_param.dy;
- do_div(high_output, btm_param.adc_vref);
+ high_output = div64_s64(high_output, btm_param.adc_vref);
high_output += btm_param.adc_gnd;
/* btm low temperature correspondes to high voltage threshold */
@@ -1616,7 +1625,7 @@
pr_debug("low_output:%lld\n", low_output);
low_output *= btm_param.dy;
- do_div(low_output, btm_param.adc_vref);
+ low_output = div64_s64(low_output, btm_param.adc_vref);
low_output += btm_param.adc_gnd;
rc = qpnp_adc_map_voltage_temp(
@@ -1631,7 +1640,7 @@
pr_debug("high_output:%lld\n", high_output);
high_output *= btm_param.dy;
- do_div(high_output, btm_param.adc_vref);
+ high_output = div64_s64(high_output, btm_param.adc_vref);
high_output += btm_param.adc_gnd;
/* btm low temperature correspondes to high voltage threshold */
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 0b86c61..c925a69 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -1180,6 +1180,7 @@
static int at91_twi_resume_noirq(struct device *dev)
{
+ struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
int ret;
if (!pm_runtime_status_suspended(dev)) {
@@ -1191,6 +1192,8 @@
pm_runtime_mark_last_busy(dev);
pm_request_autosuspend(dev);
+ at91_init_twi_bus(twi_dev);
+
return 0;
}
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index 0a6beb3..56cf590 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -1208,7 +1208,7 @@
ret = xadc->ops->setup(pdev, indio_dev, irq);
if (ret)
- goto err_free_samplerate_trigger;
+ goto err_clk_disable_unprepare;
ret = request_irq(irq, xadc->ops->interrupt_handler, 0,
dev_name(&pdev->dev), indio_dev);
@@ -1268,6 +1268,8 @@
err_free_irq:
free_irq(irq, indio_dev);
+err_clk_disable_unprepare:
+ clk_disable_unprepare(xadc->clk);
err_free_samplerate_trigger:
if (xadc->ops->flags & XADC_FLAGS_BUFFERED)
iio_trigger_free(xadc->samplerate_trigger);
@@ -1277,8 +1279,6 @@
err_triggered_buffer_cleanup:
if (xadc->ops->flags & XADC_FLAGS_BUFFERED)
iio_triggered_buffer_cleanup(indio_dev);
-err_clk_disable_unprepare:
- clk_disable_unprepare(xadc->clk);
err_device_free:
kfree(indio_dev->channels);
diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c
index 34cfd34..a3dd27b 100644
--- a/drivers/infiniband/hw/hfi1/init.c
+++ b/drivers/infiniband/hw/hfi1/init.c
@@ -297,14 +297,15 @@
* The resulting value will be rounded down to the closest
* multiple of dd->rcv_entries.group_size.
*/
- rcd->egrbufs.buffers = kcalloc(rcd->egrbufs.count,
- sizeof(*rcd->egrbufs.buffers),
- GFP_KERNEL);
+ rcd->egrbufs.buffers = kzalloc_node(
+ rcd->egrbufs.count * sizeof(*rcd->egrbufs.buffers),
+ GFP_KERNEL, numa);
if (!rcd->egrbufs.buffers)
goto bail;
- rcd->egrbufs.rcvtids = kcalloc(rcd->egrbufs.count,
- sizeof(*rcd->egrbufs.rcvtids),
- GFP_KERNEL);
+ rcd->egrbufs.rcvtids = kzalloc_node(
+ rcd->egrbufs.count *
+ sizeof(*rcd->egrbufs.rcvtids),
+ GFP_KERNEL, numa);
if (!rcd->egrbufs.rcvtids)
goto bail;
rcd->egrbufs.size = eager_buffer_size;
@@ -322,8 +323,8 @@
rcd->egrbufs.rcvtid_size = HFI1_MAX_EAGER_BUFFER_SIZE;
if (ctxt < dd->first_user_ctxt) { /* N/A for PSM contexts */
- rcd->opstats = kzalloc(sizeof(*rcd->opstats),
- GFP_KERNEL);
+ rcd->opstats = kzalloc_node(sizeof(*rcd->opstats),
+ GFP_KERNEL, numa);
if (!rcd->opstats)
goto bail;
}
diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c
index 4ac8f33..335613a1 100644
--- a/drivers/infiniband/hw/hfi1/pcie.c
+++ b/drivers/infiniband/hw/hfi1/pcie.c
@@ -673,12 +673,12 @@
#define UNSET_PSET 255
#define DEFAULT_DISCRETE_PSET 2 /* discrete HFI */
-#define DEFAULT_MCP_PSET 4 /* MCP HFI */
+#define DEFAULT_MCP_PSET 6 /* MCP HFI */
static uint pcie_pset = UNSET_PSET;
module_param(pcie_pset, uint, S_IRUGO);
MODULE_PARM_DESC(pcie_pset, "PCIe Eq Pset value to use, range is 0-10");
-static uint pcie_ctle = 1; /* discrete on, integrated off */
+static uint pcie_ctle = 3; /* discrete on, integrated on */
module_param(pcie_ctle, uint, S_IRUGO);
MODULE_PARM_DESC(pcie_ctle, "PCIe static CTLE mode, bit 0 - discrete on/off, bit 1 - integrated on/off");
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index c380b7e..1a0b110 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3120,6 +3120,7 @@
mutex_unlock(&domain->api_lock);
domain_flush_tlb_pde(domain);
+ domain_flush_complete(domain);
return unmap_size;
}
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index 1eef56a..05bbf17 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -198,7 +198,8 @@
static int __init crossbar_of_init(struct device_node *node)
{
- int i, size, max = 0, reserved = 0, entry;
+ int i, size, reserved = 0;
+ u32 max = 0, entry;
const __be32 *irqsr;
int ret = -ENOMEM;
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index b0c0aef..12abf69 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -223,7 +223,8 @@
* oldconf until no one uses it anymore.
*/
mddev_suspend(mddev);
- oldconf = rcu_dereference(mddev->private);
+ oldconf = rcu_dereference_protected(mddev->private,
+ lockdep_is_held(&mddev->reconfig_mutex));
mddev->raid_disks++;
WARN_ONCE(mddev->raid_disks != newconf->raid_disks,
"copied raid_disks doesn't match mddev->raid_disks");
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 ab3223e..d19e475 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -2513,6 +2513,45 @@
req->finished = true;
}
+void sde_rotator_abort_inline_request(struct sde_rot_mgr *mgr,
+ struct sde_rot_file_private *private,
+ struct sde_rot_entry_container *req)
+{
+ struct kthread_work *commit_work;
+ struct kthread_work *done_work;
+ struct sde_rot_entry *entry;
+ struct sde_rot_hw_resource *hw;
+ int i;
+
+ if (!mgr || !private || !req || !req->entries)
+ return;
+
+ for (i = 0; i < req->count; i++) {
+ entry = &req->entries[i];
+ if (!entry)
+ continue;
+
+ commit_work = &entry->commit_work;
+ done_work = &entry->done_work;
+
+ hw = sde_rotator_get_hw_resource(entry->commitq, entry);
+ if (!hw) {
+ SDEROT_ERR("no hw for the queue\n");
+ SDEROT_EVTLOG(i, req->count, SDE_ROT_EVTLOG_ERROR);
+ continue;
+ }
+
+ SDEROT_EVTLOG(i, req->count);
+
+ mgr->ops_abort_hw(hw, entry);
+
+ sde_rot_mgr_unlock(mgr);
+ kthread_flush_work(commit_work);
+ kthread_flush_work(done_work);
+ sde_rot_mgr_lock(mgr);
+ }
+}
+
int sde_rotator_handle_request_common(struct sde_rot_mgr *mgr,
struct sde_rot_file_private *private,
struct sde_rot_entry_container *req)
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 57a68ed..3edb2d0 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
@@ -449,6 +449,8 @@
struct sde_rot_entry *entry);
int (*ops_cancel_hw)(struct sde_rot_hw_resource *hw,
struct sde_rot_entry *entry);
+ int (*ops_abort_hw)(struct sde_rot_hw_resource *hw,
+ struct sde_rot_entry *entry);
int (*ops_kickoff_entry)(struct sde_rot_hw_resource *hw,
struct sde_rot_entry *entry);
int (*ops_wait_for_entry)(struct sde_rot_hw_resource *hw,
@@ -670,6 +672,19 @@
struct sde_rot_entry_container *req);
/*
+ * sde_rotator_abort_inline_request - abort inline rotation request after start
+ * This function allows inline rotation requests to be aborted after
+ * sde_rotator_req_set_start has already been issued.
+ * @mgr: Pointer to rotator manager
+ * @private: Pointer to rotator manager per file context
+ * @req: Pointer to rotation request
+ * return: none
+ */
+void sde_rotator_abort_inline_request(struct sde_rot_mgr *mgr,
+ struct sde_rot_file_private *private,
+ struct sde_rot_entry_container *req);
+
+/*
* sde_rotator_handle_request_common - add the given request to rotator
* manager and clean up completed requests
* @rot_dev: Pointer to rotator device
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index a90bc4c..52aadfa 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -1731,6 +1731,16 @@
sde_rotator_req_finish(rot_dev->mgr, ctx->private, req);
sde_rotator_retire_request(request);
+ } else if (cmd_type == SDE_ROTATOR_INLINE_CMD_ABORT) {
+ if (!cmd->priv_handle) {
+ ret = -EINVAL;
+ SDEROT_ERR("invalid private handle\n");
+ goto error_invalid_handle;
+ }
+
+ request = cmd->priv_handle;
+ sde_rotator_abort_inline_request(rot_dev->mgr,
+ ctx->private, request->req);
}
sde_rot_mgr_unlock(rot_dev->mgr);
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h
index 474662e..ba70489 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_inline.h
@@ -27,12 +27,14 @@
* @SDE_ROTATOR_INLINE_CMD_COMMIT: commit command to hardware
* @SDE_ROTATOR_INLINE_CMD_START: ready to start inline rotation
* @SDE_ROTATOR_INLINE_CMD_CLEANUP: cleanup after commit is done
+ * @SDE_ROTATOR_INLINE_CMD_ABORT: abort current commit and reset
*/
enum sde_rotator_inline_cmd_type {
SDE_ROTATOR_INLINE_CMD_VALIDATE,
SDE_ROTATOR_INLINE_CMD_COMMIT,
SDE_ROTATOR_INLINE_CMD_START,
SDE_ROTATOR_INLINE_CMD_CLEANUP,
+ SDE_ROTATOR_INLINE_CMD_ABORT,
};
/**
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r1.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r1.c
index 89ad438..40db488 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r1.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r1.c
@@ -349,6 +349,12 @@
return 0;
}
+static int sde_rotator_abort_hw(struct sde_rot_hw_resource *hw,
+ struct sde_rot_entry *entry)
+{
+ return 0;
+}
+
static int sde_rotator_kickoff_entry(struct sde_rot_hw_resource *hw,
struct sde_rot_entry *entry)
{
@@ -691,6 +697,7 @@
mgr->hw_data = hw_data;
mgr->ops_config_hw = sde_rotator_config_hw;
mgr->ops_cancel_hw = sde_rotator_cancel_hw;
+ mgr->ops_abort_hw = sde_rotator_abort_hw;
mgr->ops_kickoff_entry = sde_rotator_kickoff_entry;
mgr->ops_wait_for_entry = sde_rotator_wait_for_entry;
mgr->ops_hw_alloc = sde_rotator_hw_alloc_ext;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index f7b4e6e..c5da084 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -51,6 +51,12 @@
/* wait for at most 2 vsync for lowest refresh rate (24hz) */
#define KOFF_TIMEOUT (42 * 8)
+/*
+ * When in sbuf mode, select a much longer wait, to allow the other driver
+ * to detect timeouts and abort if necessary.
+ */
+#define KOFF_TIMEOUT_SBUF (2000)
+
/* default stream buffer headroom in lines */
#define DEFAULT_SBUF_HEADROOM 20
#define DEFAULT_UBWC_MALSIZE 0
@@ -1766,6 +1772,8 @@
mask = ~(SDE_REGDMA_SWTS_MASK << SDE_REGDMA_SWTS_SHIFT);
}
+ SDEROT_EVTLOG(ctx->timestamp, queue_id, length, offset, ctx->sbuf_mode);
+
/* timestamp update can only be used in offline multi-context mode */
if (!ctx->sbuf_mode) {
/* Write timestamp after previous rotator job finished */
@@ -1778,6 +1786,8 @@
/* ensure command packet is issue before the submit command */
wmb();
+ SDEROT_EVTLOG(queue_id, enableInt, ts_length, offset);
+
if (queue_id == ROT_QUEUE_HIGH_PRIORITY) {
SDE_ROTREG_WRITE(rot->mdss_base,
REGDMA_CSR_REGDMA_QUEUE_0_SUBMIT,
@@ -1814,6 +1824,8 @@
if (rot->irq_num >= 0) {
SDEROT_DBG("Wait for Rotator completion\n");
rc = wait_for_completion_timeout(&ctx->rot_comp,
+ ctx->sbuf_mode ?
+ msecs_to_jiffies(KOFF_TIMEOUT_SBUF) :
msecs_to_jiffies(rot->koff_timeout));
spin_lock_irqsave(&rot->rotisr_lock, flags);
@@ -1872,6 +1884,7 @@
{
struct sde_hw_rotator *rot = ctx->rot;
int rc = 0;
+ bool abort;
u32 status;
u32 last_isr;
u32 last_ts;
@@ -1886,6 +1899,8 @@
ctx, ctx->timestamp);
rc = wait_event_timeout(ctx->regdma_waitq,
!sde_hw_rotator_pending_swts(rot, ctx, &swts),
+ ctx->sbuf_mode ?
+ msecs_to_jiffies(KOFF_TIMEOUT_SBUF) :
msecs_to_jiffies(rot->koff_timeout));
ATRACE_INT("sde_rot_done", 0);
@@ -1893,18 +1908,19 @@
last_isr = ctx->last_regdma_isr_status;
last_ts = ctx->last_regdma_timestamp;
+ abort = ctx->abort;
status = last_isr & REGDMA_INT_MASK;
int_id = last_ts & 1;
SDEROT_DBG("INT status:0x%X, INT id:%d, timestamp:0x%X\n",
status, int_id, last_ts);
- if (rc == 0 || (status & REGDMA_INT_ERR_MASK)) {
+ if (rc == 0 || (status & REGDMA_INT_ERR_MASK) || abort) {
bool pending;
pending = sde_hw_rotator_pending_swts(rot, ctx, &swts);
SDEROT_ERR(
- "Timeout wait for regdma interrupt status, ts:0x%X/0x%X pending:%d\n",
- ctx->timestamp, swts, pending);
+ "Timeout wait for regdma interrupt status, ts:0x%X/0x%X, pending:%d, abort:%d\n",
+ ctx->timestamp, swts, pending, abort);
if (status & REGDMA_WATCHDOG_INT)
SDEROT_ERR("REGDMA watchdog interrupt\n");
@@ -1917,7 +1933,7 @@
sde_hw_rotator_dump_status(rot, &ubwcerr);
- if (ubwcerr) {
+ if (ubwcerr || abort) {
/*
* Perform recovery for ROT SSPP UBWC decode
* error.
@@ -2756,6 +2772,42 @@
return 0;
}
+static int sde_hw_rotator_abort_kickoff(struct sde_rot_hw_resource *hw,
+ struct sde_rot_entry *entry)
+{
+ struct sde_hw_rotator *rot;
+ struct sde_hw_rotator_resource_info *resinfo;
+ struct sde_hw_rotator_context *ctx;
+ unsigned long flags;
+
+ if (!hw || !entry) {
+ SDEROT_ERR("null hw resource/entry\n");
+ return -EINVAL;
+ }
+
+ resinfo = container_of(hw, struct sde_hw_rotator_resource_info, hw);
+ rot = resinfo->rot;
+
+ /* Lookup rotator context from session-id */
+ ctx = sde_hw_rotator_get_ctx(rot, entry->item.session_id,
+ entry->item.sequence_id, hw->wb_id);
+ if (!ctx) {
+ SDEROT_ERR("Cannot locate rotator ctx from sesison id:%d\n",
+ entry->item.session_id);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&rot->rotisr_lock, flags);
+ sde_hw_rotator_update_swts(rot, ctx, ctx->timestamp);
+ ctx->abort = true;
+ wake_up_all(&ctx->regdma_waitq);
+ spin_unlock_irqrestore(&rot->rotisr_lock, flags);
+
+ SDEROT_EVTLOG(entry->item.session_id, ctx->timestamp);
+
+ return 0;
+}
+
/*
* sde_hw_rotator_wait4done - wait for completion notification
* @hw: Pointer to rotator resource
@@ -3535,6 +3587,7 @@
mgr->ops_hw_free = sde_hw_rotator_free_ext;
mgr->ops_config_hw = sde_hw_rotator_config;
mgr->ops_cancel_hw = sde_hw_rotator_cancel;
+ mgr->ops_abort_hw = sde_hw_rotator_abort_kickoff;
mgr->ops_kickoff_entry = sde_hw_rotator_kickoff;
mgr->ops_wait_for_entry = sde_hw_rotator_wait4done;
mgr->ops_hw_validate_entry = sde_hw_rotator_validate_entry;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
index 8b391ea..1ff43d6 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
@@ -231,6 +231,7 @@
bool is_secure;
bool is_traffic_shaping;
bool sbuf_mode;
+ bool abort;
u32 start_ctrl;
u32 sys_cache_mode;
u32 op_mode;
diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
index 45e8771..83b80d7 100644
--- a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
+++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
@@ -462,7 +462,7 @@
bw_for_1x_8bpc = fp_div(FP_INT(width * height), FP_INT(32 * 8));
bw_for_1x_8bpc = fp_mult(bw_for_1x_8bpc,
- fp_div(FP_INT(256 * 30), FP_INT(1000 * 1000)));
+ fp_div(FP_INT(((int)(256 * fps))), FP_INT(1000 * 1000)));
dpb_bw_for_1x = dpb_bpp == 8 ? bw_for_1x_8bpc :
fp_mult(bw_for_1x_8bpc, fp_mult(ten_bpc_packing_factor,
@@ -715,7 +715,7 @@
bw_for_1x_8bpc = fp_div(FP_INT(width * height), FP_INT(32 * 8));
bw_for_1x_8bpc = fp_mult(bw_for_1x_8bpc,
- fp_div(FP_INT(256 * 30), FP_INT(1000 * 1000)));
+ fp_div(FP_INT(((int)(256 * fps))), FP_INT(1000 * 1000)));
dpb_bw_for_1x = dpb_bpp == 8 ? bw_for_1x_8bpc :
fp_mult(bw_for_1x_8bpc, fp_mult(ten_bpc_packing_factor,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 5183ddd..e258f1f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -146,7 +146,7 @@
vote_data->use_dpb_read = false;
/* Check if driver can vote for lower bus BW */
- if (inst->clk_data.load <= inst->clk_data.load_norm) {
+ if (inst->clk_data.load < inst->clk_data.load_norm) {
vote_data->compression_ratio = max_cr;
vote_data->complexity_factor = min_cf;
vote_data->input_cr = max_input_cr;
@@ -283,9 +283,11 @@
return rc;
}
-static inline int get_pending_bufs_fw(struct msm_vidc_inst *inst)
+static inline int get_bufs_outside_fw(struct msm_vidc_inst *inst)
{
- int fw_out_qsize = 0;
+ u32 fw_out_qsize = 0, i = 0;
+ struct vb2_queue *q = NULL;
+ struct vb2_buffer *vb = NULL;
/*
* DCVS always operates on Uncompressed buffers.
@@ -294,10 +296,29 @@
if (inst->state >= MSM_VIDC_OPEN_DONE &&
inst->state < MSM_VIDC_STOP_DONE) {
- if (inst->session_type == MSM_VIDC_DECODER)
- fw_out_qsize = inst->count.ftb - inst->count.fbd;
- else
- fw_out_qsize = inst->count.etb - inst->count.ebd;
+
+ /*
+ * For decoder, there will be some frames with client
+ * but not to be displayed. Ex : VP9 DECODE_ONLY frames.
+ * Hence don't count them.
+ */
+
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ q = &inst->bufq[CAPTURE_PORT].vb2_bufq;
+ for (i = 0; i < q->num_buffers; i++) {
+ vb = q->bufs[i];
+ if (vb->state != VB2_BUF_STATE_ACTIVE &&
+ vb->planes[0].bytesused)
+ fw_out_qsize++;
+ }
+ } else {
+ q = &inst->bufq[OUTPUT_PORT].vb2_bufq;
+ for (i = 0; i < q->num_buffers; i++) {
+ vb = q->bufs[i];
+ if (vb->state != VB2_BUF_STATE_ACTIVE)
+ fw_out_qsize++;
+ }
+ }
}
return fw_out_qsize;
@@ -328,7 +349,7 @@
core = inst->core;
mutex_lock(&inst->lock);
- fw_pending_bufs = get_pending_bufs_fw(inst);
+ buffers_outside_fw = get_bufs_outside_fw(inst);
output_buf_req = get_buff_req_buffer(inst,
dcvs->buffer_type);
@@ -345,8 +366,8 @@
min_output_buf = output_buf_req->buffer_count_min;
- /* Buffers outside FW are with display */
- buffers_outside_fw = total_output_buf - fw_pending_bufs;
+ /* Buffers outside Display are with FW. */
+ fw_pending_bufs = total_output_buf - buffers_outside_fw;
dprintk(VIDC_PROF,
"Counts : total_output_buf = %d Min buffers = %d fw_pending_bufs = %d buffers_outside_fw = %d\n",
total_output_buf, min_output_buf, fw_pending_bufs,
@@ -372,7 +393,7 @@
if (buffers_outside_fw <= dcvs->max_threshold)
dcvs->load = dcvs->load_high;
- else if (fw_pending_bufs <= min_output_buf)
+ else if (fw_pending_bufs < min_output_buf)
dcvs->load = dcvs->load_low;
else
dcvs->load = dcvs->load_norm;
@@ -877,10 +898,7 @@
return;
}
dcvs->max_threshold = output_buf_req->buffer_count_actual -
- output_buf_req->buffer_count_min_host + 1;
- /* Compensate for decode only frames */
- if (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9)
- dcvs->max_threshold += 2;
+ output_buf_req->buffer_count_min_host + 2;
dcvs->min_threshold =
msm_vidc_get_extra_buff_count(inst, dcvs->buffer_type);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index fe5dad7..338d6f1 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -2616,6 +2616,8 @@
if (!strcmp((void *)ptr_app->app_name,
(void *)data->client.app_name)) {
found_app = true;
+ if (ptr_app->app_blocked)
+ app_crash = false;
if (app_crash || ptr_app->ref_cnt == 1)
unload = true;
break;
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index a209aa6..538a8d9 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1221,16 +1221,16 @@
if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
mmc_blk_part_switch(card, dev_get_drvdata(&card->dev));
- mmc_put_card(card);
-
- err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
-
if (mmc_card_cmdq(card)) {
if (mmc_cmdq_halt(card->host, false))
pr_err("%s: %s: cmdq unhalt failed\n",
mmc_hostname(card->host), __func__);
}
+ mmc_put_card(card);
+
+ err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
+
cmd_done:
mmc_blk_put(md);
cmd_err:
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 7163e34..15c3e9e 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -669,9 +669,10 @@
{
struct mmc_card *card = filp->private_data;
struct mmc_wr_pack_stats *pack_stats;
- int i;
+ int i, ret = 0;
int max_num_of_packed_reqs = 0;
- char *temp_buf;
+ char *temp_buf, *temp_ubuf;
+ size_t tubuf_cnt = 0;
if (!card)
return cnt;
@@ -697,15 +698,24 @@
max_num_of_packed_reqs = card->ext_csd.max_packed_writes;
- temp_buf = kmalloc(TEMP_BUF_SIZE, GFP_KERNEL);
+ if (cnt <= (strlen_user(ubuf) + 1))
+ goto exit;
+
+ temp_buf = kzalloc(TEMP_BUF_SIZE, GFP_KERNEL);
if (!temp_buf)
goto exit;
+ tubuf_cnt = cnt - strlen_user(ubuf) - 1;
+
+ temp_ubuf = kzalloc(tubuf_cnt, GFP_KERNEL);
+ if (!temp_ubuf)
+ goto cleanup;
+
spin_lock(&pack_stats->lock);
snprintf(temp_buf, TEMP_BUF_SIZE, "%s: write packing statistics:\n",
mmc_hostname(card->host));
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
for (i = 1 ; i <= max_num_of_packed_reqs ; ++i) {
if (pack_stats->packing_events[i]) {
@@ -713,63 +723,63 @@
"%s: Packed %d reqs - %d times\n",
mmc_hostname(card->host), i,
pack_stats->packing_events[i]);
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
}
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: stopped packing due to the following reasons:\n",
mmc_hostname(card->host));
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
if (pack_stats->pack_stop_reason[EXCEEDS_SEGMENTS]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: exceed max num of segments\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[EXCEEDS_SEGMENTS]);
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[EXCEEDS_SECTORS]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: exceed max num of sectors\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[EXCEEDS_SECTORS]);
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[WRONG_DATA_DIR]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: wrong data direction\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[WRONG_DATA_DIR]);
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[FLUSH_OR_DISCARD]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: flush or discard\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[FLUSH_OR_DISCARD]);
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[EMPTY_QUEUE]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: empty queue\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[EMPTY_QUEUE]);
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[REL_WRITE]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: rel write\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[REL_WRITE]);
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[THRESHOLD]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: Threshold\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[THRESHOLD]);
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[LARGE_SEC_ALIGN]) {
@@ -777,25 +787,36 @@
"%s: %d times: Large sector alignment\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[LARGE_SEC_ALIGN]);
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[RANDOM]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: random request\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[RANDOM]);
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
if (pack_stats->pack_stop_reason[FUA]) {
snprintf(temp_buf, TEMP_BUF_SIZE,
"%s: %d times: fua request\n",
mmc_hostname(card->host),
pack_stats->pack_stop_reason[FUA]);
- strlcat(ubuf, temp_buf, cnt);
+ strlcat(temp_ubuf, temp_buf, tubuf_cnt);
}
+ if (strlen_user(ubuf) < cnt - strlen(temp_ubuf))
+ ret = copy_to_user((ubuf + strlen_user(ubuf)),
+ temp_ubuf, tubuf_cnt);
+ else
+ ret = -EFAULT;
+ if (ret)
+ pr_err("%s: %s: Copy to userspace failed: %s\n",
+ mmc_hostname(card->host), __func__, ubuf);
spin_unlock(&pack_stats->lock);
+ kfree(temp_ubuf);
+
+cleanup:
kfree(temp_buf);
pr_info("%s", ubuf);
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 0a4e81a..ed6fae9 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -4413,13 +4413,12 @@
struct mvpp2_txq_pcpu_buf *tx_buf =
txq_pcpu->buffs + txq_pcpu->txq_get_index;
- mvpp2_txq_inc_get(txq_pcpu);
-
dma_unmap_single(port->dev->dev.parent, tx_buf->phys,
tx_buf->size, DMA_TO_DEVICE);
- if (!tx_buf->skb)
- continue;
- dev_kfree_skb_any(tx_buf->skb);
+ if (tx_buf->skb)
+ dev_kfree_skb_any(tx_buf->skb);
+
+ mvpp2_txq_inc_get(txq_pcpu);
}
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
index a5fc46b..d4d97ca 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
@@ -88,10 +88,17 @@
}
}
+#define MLX4_EN_WRAP_AROUND_SEC 10UL
+/* By scheduling the overflow check every 5 seconds, we have a reasonably
+ * good chance we wont miss a wrap around.
+ * TOTO: Use a timer instead of a work queue to increase the guarantee.
+ */
+#define MLX4_EN_OVERFLOW_PERIOD (MLX4_EN_WRAP_AROUND_SEC * HZ / 2)
+
void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev)
{
bool timeout = time_is_before_jiffies(mdev->last_overflow_check +
- mdev->overflow_period);
+ MLX4_EN_OVERFLOW_PERIOD);
unsigned long flags;
if (timeout) {
@@ -236,7 +243,6 @@
.enable = mlx4_en_phc_enable,
};
-#define MLX4_EN_WRAP_AROUND_SEC 10ULL
/* This function calculates the max shift that enables the user range
* of MLX4_EN_WRAP_AROUND_SEC values in the cycles register.
@@ -261,7 +267,6 @@
{
struct mlx4_dev *dev = mdev->dev;
unsigned long flags;
- u64 ns, zero = 0;
/* mlx4_en_init_timestamp is called for each netdev.
* mdev->ptp_clock is common for all ports, skip initialization if
@@ -285,13 +290,6 @@
ktime_to_ns(ktime_get_real()));
write_unlock_irqrestore(&mdev->clock_lock, flags);
- /* Calculate period in seconds to call the overflow watchdog - to make
- * sure counter is checked at least once every wrap around.
- */
- ns = cyclecounter_cyc2ns(&mdev->cycles, mdev->cycles.mask, zero, &zero);
- do_div(ns, NSEC_PER_SEC / 2 / HZ);
- mdev->overflow_period = ns;
-
/* Configure the PHC */
mdev->ptp_clock_info = mlx4_en_ptp_clock_info;
snprintf(mdev->ptp_clock_info.name, 16, "mlx4 ptp");
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index ba652d8..727122d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -841,8 +841,6 @@
return -ENOSYS;
}
- mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz;
-
dev->caps.hca_core_clock = hca_param.hca_core_clock;
memset(&dev_cap, 0, sizeof(dev_cap));
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index a3528dd..df0f396 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -419,7 +419,6 @@
struct cyclecounter cycles;
struct timecounter clock;
unsigned long last_overflow_check;
- unsigned long overflow_period;
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_clock_info;
struct notifier_block nb;
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index 653bb57..433f8be 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -642,7 +642,9 @@
#define OOO_LB_TC 9
int qed_configure_vport_wfq(struct qed_dev *cdev, u16 vp_id, u32 rate);
-void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev, u32 min_pf_rate);
+void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev,
+ struct qed_ptt *p_ptt,
+ u32 min_pf_rate);
void qed_clean_wfq_db(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
#define QED_LEADING_HWFN(dev) (&dev->hwfns[0])
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index edae5fc..afe5e57 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -877,7 +877,7 @@
/* Either EDPM is mandatory, or we are attempting to allocate a
* WID per CPU.
*/
- n_cpus = num_active_cpus();
+ n_cpus = num_present_cpus();
rc = qed_hw_init_dpi_size(p_hwfn, p_ptt, pwm_regsize, n_cpus);
}
@@ -2732,7 +2732,8 @@
}
/* API to configure WFQ from mcp link change */
-void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev, u32 min_pf_rate)
+void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev,
+ struct qed_ptt *p_ptt, u32 min_pf_rate)
{
int i;
@@ -2746,8 +2747,7 @@
for_each_hwfn(cdev, i) {
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
- __qed_configure_vp_wfq_on_link_change(p_hwfn,
- p_hwfn->p_dpc_ptt,
+ __qed_configure_vp_wfq_on_link_change(p_hwfn, p_ptt,
min_pf_rate);
}
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index bdc9ba9..8b7d2f9 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -628,7 +628,8 @@
/* Min bandwidth configuration */
__qed_configure_pf_min_bandwidth(p_hwfn, p_ptt, p_link, min_bw);
- qed_configure_vp_wfq_on_link_change(p_hwfn->cdev, p_link->min_pf_rate);
+ qed_configure_vp_wfq_on_link_change(p_hwfn->cdev, p_ptt,
+ p_link->min_pf_rate);
p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED);
p_link->an_complete = !!(status &
diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c
index f3a825a..d9dcb0d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_roce.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c
@@ -1766,13 +1766,13 @@
if (rc)
goto err_resp;
- dma_free_coherent(&p_hwfn->cdev->pdev->dev, sizeof(*p_resp_ramrod_res),
- p_resp_ramrod_res, resp_ramrod_res_phys);
-
out_params->rq_psn = le32_to_cpu(p_resp_ramrod_res->psn);
rq_err_state = GET_FIELD(le32_to_cpu(p_resp_ramrod_res->err_flag),
ROCE_QUERY_QP_RESP_OUTPUT_PARAMS_ERROR_FLG);
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev, sizeof(*p_resp_ramrod_res),
+ p_resp_ramrod_res, resp_ramrod_res_phys);
+
if (!(qp->req_offloaded)) {
/* Don't send query qp for the requester */
out_params->sq_psn = qp->sq_psn;
@@ -1813,9 +1813,6 @@
if (rc)
goto err_req;
- dma_free_coherent(&p_hwfn->cdev->pdev->dev, sizeof(*p_req_ramrod_res),
- p_req_ramrod_res, req_ramrod_res_phys);
-
out_params->sq_psn = le32_to_cpu(p_req_ramrod_res->psn);
sq_err_state = GET_FIELD(le32_to_cpu(p_req_ramrod_res->flags),
ROCE_QUERY_QP_REQ_OUTPUT_PARAMS_ERR_FLG);
@@ -1823,6 +1820,9 @@
GET_FIELD(le32_to_cpu(p_req_ramrod_res->flags),
ROCE_QUERY_QP_REQ_OUTPUT_PARAMS_SQ_DRAINING_FLG);
+ dma_free_coherent(&p_hwfn->cdev->pdev->dev, sizeof(*p_req_ramrod_res),
+ p_req_ramrod_res, req_ramrod_res_phys);
+
out_params->draining = false;
if (rq_err_state)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 7567cc4..634e414 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -1221,7 +1221,7 @@
struct qede_rx_queue *rxq = NULL;
struct sw_rx_data *sw_rx_data;
union eth_rx_cqe *cqe;
- int i, rc = 0;
+ int i, iter, rc = 0;
u8 *data_ptr;
for_each_queue(i) {
@@ -1240,7 +1240,7 @@
* enabled. This is because the queue 0 is configured as the default
* queue and that the loopback traffic is not IP.
*/
- for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) {
+ for (iter = 0; iter < QEDE_SELFTEST_POLL_COUNT; iter++) {
if (!qede_has_rx_work(rxq)) {
usleep_range(100, 200);
continue;
@@ -1287,7 +1287,7 @@
qed_chain_recycle_consumed(&rxq->rx_comp_ring);
}
- if (i == QEDE_SELFTEST_POLL_COUNT) {
+ if (iter == QEDE_SELFTEST_POLL_COUNT) {
DP_NOTICE(edev, "Failed to receive the traffic\n");
return -1;
}
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index c06932c..d2a28a9 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -3046,6 +3046,7 @@
static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
{
struct hwsim_new_radio_params param = { 0 };
+ const char *hwname = NULL;
param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG];
param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE];
@@ -3059,8 +3060,14 @@
if (info->attrs[HWSIM_ATTR_NO_VIF])
param.no_vif = true;
- if (info->attrs[HWSIM_ATTR_RADIO_NAME])
- param.hwname = nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]);
+ if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
+ hwname = kasprintf(GFP_KERNEL, "%.*s",
+ nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
+ (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]));
+ if (!hwname)
+ return -ENOMEM;
+ param.hwname = hwname;
+ }
if (info->attrs[HWSIM_ATTR_USE_CHANCTX])
param.use_chanctx = true;
@@ -3088,11 +3095,15 @@
s64 idx = -1;
const char *hwname = NULL;
- if (info->attrs[HWSIM_ATTR_RADIO_ID])
+ if (info->attrs[HWSIM_ATTR_RADIO_ID]) {
idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]);
- else if (info->attrs[HWSIM_ATTR_RADIO_NAME])
- hwname = (void *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]);
- else
+ } else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
+ hwname = kasprintf(GFP_KERNEL, "%.*s",
+ nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
+ (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]));
+ if (!hwname)
+ return -ENOMEM;
+ } else
return -EINVAL;
spin_lock_bh(&hwsim_radio_lock);
@@ -3101,7 +3112,8 @@
if (data->idx != idx)
continue;
} else {
- if (strcmp(hwname, wiphy_name(data->hw->wiphy)))
+ if (!hwname ||
+ strcmp(hwname, wiphy_name(data->hw->wiphy)))
continue;
}
@@ -3112,10 +3124,12 @@
spin_unlock_bh(&hwsim_radio_lock);
mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy),
info);
+ kfree(hwname);
return 0;
}
spin_unlock_bh(&hwsim_radio_lock);
+ kfree(hwname);
return -ENODEV;
}
diff --git a/drivers/net/xen-netback/hash.c b/drivers/net/xen-netback/hash.c
index e8c5ddd..3c4c58b 100644
--- a/drivers/net/xen-netback/hash.c
+++ b/drivers/net/xen-netback/hash.c
@@ -39,7 +39,7 @@
unsigned long flags;
bool found;
- new = kmalloc(sizeof(*entry), GFP_KERNEL);
+ new = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (!new)
return;
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 0e75d94..671610c 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -82,6 +82,7 @@
tristate "AMD GPIO pin control"
depends on GPIOLIB
select GPIOLIB_IRQCHIP
+ select PINMUX
select PINCONF
select GENERIC_PINCONF
help
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index c02881b..6727da6 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -24,8 +24,6 @@
#define GSI_CMD_TIMEOUT (5*HZ)
#define GSI_STOP_CMD_TIMEOUT_MS 20
#define GSI_MAX_CH_LOW_WEIGHT 15
-#define GSI_MHI_ER_START 10
-#define GSI_MHI_ER_END 16
#define GSI_RESET_WA_MIN_SLEEP 1000
#define GSI_RESET_WA_MAX_SLEEP 2000
@@ -829,10 +827,23 @@
return -GSI_STATUS_ERROR;
}
- /* bitmap is max events excludes reserved events */
+ if (props->mhi_er_id_limits_valid &&
+ props->mhi_er_id_limits[0] > (gsi_ctx->max_ev - 1)) {
+ devm_iounmap(gsi_ctx->dev, gsi_ctx->base);
+ gsi_ctx->base = NULL;
+ devm_free_irq(gsi_ctx->dev, props->irq, gsi_ctx);
+ GSIERR("MHI event ring start id %u is beyond max %u\n",
+ props->mhi_er_id_limits[0], gsi_ctx->max_ev);
+ return -GSI_STATUS_ERROR;
+ }
+
gsi_ctx->evt_bmap = ~((1 << gsi_ctx->max_ev) - 1);
- gsi_ctx->evt_bmap |= ((1 << (GSI_MHI_ER_END + 1)) - 1) ^
- ((1 << GSI_MHI_ER_START) - 1);
+
+ /* exclude reserved mhi events */
+ if (props->mhi_er_id_limits_valid)
+ gsi_ctx->evt_bmap |=
+ ((1 << (props->mhi_er_id_limits[1] + 1)) - 1) ^
+ ((1 << (props->mhi_er_id_limits[0])) - 1);
/*
* enable all interrupts but GSI_BREAK_POINT.
@@ -1084,8 +1095,8 @@
if (props->intf == GSI_EVT_CHTYPE_MHI_EV &&
(!props->evchid_valid ||
- props->evchid > GSI_MHI_ER_END ||
- props->evchid < GSI_MHI_ER_START)) {
+ props->evchid > gsi_ctx->per.mhi_er_id_limits[1] ||
+ props->evchid < gsi_ctx->per.mhi_er_id_limits[0])) {
GSIERR("MHI requires evchid valid=%d val=%u\n",
props->evchid_valid, props->evchid);
return -GSI_STATUS_INVALID_PARAMS;
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index abb714d..59e1871 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -3056,6 +3056,18 @@
return ret;
}
+/**
+ * ipa_tz_unlock_reg() - Allow AP access to memory regions controlled by TZ
+ */
+int ipa_tz_unlock_reg(struct ipa_tz_unlock_reg_info *reg_info, u16 num_regs)
+{
+ int ret;
+
+ IPA_API_DISPATCH_RETURN(ipa_tz_unlock_reg, reg_info, num_regs);
+
+ return ret;
+}
+
static const struct dev_pm_ops ipa_pm_ops = {
.suspend_noirq = ipa_ap_suspend,
.resume_noirq = ipa_ap_resume,
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index 7a48b68..ff1a77a 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.h
@@ -398,6 +398,9 @@
int (*ipa_disable_wdi3_pipes)(int ipa_ep_idx_tx,
int ipa_ep_idx_rx);
+
+ int (*ipa_tz_unlock_reg)(struct ipa_tz_unlock_reg_info *reg_info,
+ u16 num_regs);
};
#ifdef CONFIG_IPA
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
index e18c0d4..7a683ec 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -41,11 +41,6 @@
#define IPA_MHI_MAX_UL_CHANNELS 1
#define IPA_MHI_MAX_DL_CHANNELS 1
-#if (IPA_MHI_MAX_UL_CHANNELS + IPA_MHI_MAX_DL_CHANNELS) > \
- (IPA_MHI_GSI_ER_END - IPA_MHI_GSI_ER_START)
-#error not enought event rings for MHI
-#endif
-
/* bit #40 in address should be asserted for MHI transfers over pcie */
#define IPA_MHI_CLIENT_HOST_ADDR_COND(addr) \
((ipa_mhi_client_ctx->assert_bit40)?(IPA_MHI_HOST_ADDR(addr)):(addr))
@@ -1574,8 +1569,7 @@
internal.start.gsi.mhi = &channel->ch_scratch.mhi;
internal.start.gsi.cached_gsi_evt_ring_hdl =
&channel->cached_gsi_evt_ring_hdl;
- internal.start.gsi.evchid =
- channel->index + IPA_MHI_GSI_ER_START;
+ internal.start.gsi.evchid = channel->index;
res = ipa_connect_mhi_pipe(&internal, clnt_hdl);
if (res) {
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index fe8cbc0..0a406d2 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -145,9 +145,6 @@
u32 size;
};
-#define IPA_MHI_GSI_ER_START 10
-#define IPA_MHI_GSI_ER_END 16
-
/**
* enum ipa3_mhi_burst_mode - MHI channel burst mode state
*
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index e5aa6ef..db375ec 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -86,6 +86,9 @@
#define IPA3_ACTIVE_CLIENT_LOG_TYPE_RESOURCE 2
#define IPA3_ACTIVE_CLIENT_LOG_TYPE_SPECIAL 3
+#define IPA_MHI_GSI_EVENT_RING_ID_START 10
+#define IPA_MHI_GSI_EVENT_RING_ID_END 12
+
#define IPA_SMEM_SIZE (8 * 1024)
#define IPA_GSI_CHANNEL_HALT_MIN_SLEEP 5000
@@ -4286,6 +4289,12 @@
gsi_props.req_clk_cb = NULL;
gsi_props.rel_clk_cb = NULL;
+ if (ipa3_ctx->ipa_config_is_mhi) {
+ gsi_props.mhi_er_id_limits_valid = true;
+ gsi_props.mhi_er_id_limits[0] = resource_p->mhi_evid_limits[0];
+ gsi_props.mhi_er_id_limits[1] = resource_p->mhi_evid_limits[1];
+ }
+
result = gsi_register_device(&gsi_props,
&ipa3_ctx->gsi_dev_hdl);
if (result != GSI_STATUS_SUCCESS) {
@@ -4492,50 +4501,70 @@
return count;
}
-static int ipa3_tz_unlock_reg(struct ipa3_context *ipa3_ctx)
+/**
+ * ipa3_tz_unlock_reg - Unlocks memory regions so that they become accessible
+ * from AP.
+ * @reg_info - Pointer to array of memory regions to unlock
+ * @num_regs - Number of elements in the array
+ *
+ * Converts the input array of regions to a struct that TZ understands and
+ * issues an SCM call.
+ * Also flushes the memory cache to DDR in order to make sure that TZ sees the
+ * correct data structure.
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa3_tz_unlock_reg(struct ipa_tz_unlock_reg_info *reg_info, u16 num_regs)
{
int i, size, ret, resp;
struct tz_smmu_ipa_protect_region_iovec_s *ipa_tz_unlock_vec;
struct tz_smmu_ipa_protect_region_s cmd_buf;
+ struct scm_desc desc = {0};
- if (ipa3_ctx && ipa3_ctx->ipa_tz_unlock_reg_num > 0) {
- size = ipa3_ctx->ipa_tz_unlock_reg_num *
- sizeof(struct tz_smmu_ipa_protect_region_iovec_s);
- ipa_tz_unlock_vec = kzalloc(PAGE_ALIGN(size), GFP_KERNEL);
- if (ipa_tz_unlock_vec == NULL)
- return -ENOMEM;
-
- for (i = 0; i < ipa3_ctx->ipa_tz_unlock_reg_num; i++) {
- ipa_tz_unlock_vec[i].input_addr =
- ipa3_ctx->ipa_tz_unlock_reg[i].reg_addr ^
- (ipa3_ctx->ipa_tz_unlock_reg[i].reg_addr &
- 0xFFF);
- ipa_tz_unlock_vec[i].output_addr =
- ipa3_ctx->ipa_tz_unlock_reg[i].reg_addr ^
- (ipa3_ctx->ipa_tz_unlock_reg[i].reg_addr &
- 0xFFF);
- ipa_tz_unlock_vec[i].size =
- ipa3_ctx->ipa_tz_unlock_reg[i].size;
- ipa_tz_unlock_vec[i].attr = IPA_TZ_UNLOCK_ATTRIBUTE;
- }
-
- /* pass physical address of command buffer */
- cmd_buf.iovec_buf = virt_to_phys((void *)ipa_tz_unlock_vec);
- cmd_buf.size_bytes = size;
-
- /* flush cache to DDR */
- __cpuc_flush_dcache_area((void *)ipa_tz_unlock_vec, size);
- outer_flush_range(cmd_buf.iovec_buf, cmd_buf.iovec_buf + size);
-
- ret = scm_call(SCM_SVC_MP, TZ_MEM_PROTECT_REGION_ID, &cmd_buf,
- sizeof(cmd_buf), &resp, sizeof(resp));
- if (ret) {
- IPAERR("scm call SCM_SVC_MP failed: %d\n", ret);
- kfree(ipa_tz_unlock_vec);
- return -EFAULT;
- }
- kfree(ipa_tz_unlock_vec);
+ if (reg_info == NULL || num_regs == 0) {
+ IPAERR("Bad parameters\n");
+ return -EFAULT;
}
+
+ size = num_regs * sizeof(struct tz_smmu_ipa_protect_region_iovec_s);
+ ipa_tz_unlock_vec = kzalloc(PAGE_ALIGN(size), GFP_KERNEL);
+ if (ipa_tz_unlock_vec == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < num_regs; i++) {
+ ipa_tz_unlock_vec[i].input_addr = reg_info[i].reg_addr ^
+ (reg_info[i].reg_addr & 0xFFF);
+ ipa_tz_unlock_vec[i].output_addr = reg_info[i].reg_addr ^
+ (reg_info[i].reg_addr & 0xFFF);
+ ipa_tz_unlock_vec[i].size = reg_info[i].size;
+ ipa_tz_unlock_vec[i].attr = IPA_TZ_UNLOCK_ATTRIBUTE;
+ }
+
+ /* pass physical address of command buffer */
+ cmd_buf.iovec_buf = virt_to_phys((void *)ipa_tz_unlock_vec);
+ cmd_buf.size_bytes = size;
+
+ /* flush cache to DDR */
+ __cpuc_flush_dcache_area((void *)ipa_tz_unlock_vec, size);
+ outer_flush_range(cmd_buf.iovec_buf, cmd_buf.iovec_buf + size);
+ if (!is_scm_armv8())
+ ret = scm_call(SCM_SVC_MP, TZ_MEM_PROTECT_REGION_ID,
+ &cmd_buf, sizeof(cmd_buf), &resp, sizeof(resp));
+ else {
+ desc.args[0] = virt_to_phys((void *)ipa_tz_unlock_vec);
+ desc.args[1] = size;
+ desc.arginfo = SCM_ARGS(2, SCM_RO, SCM_VAL);
+ ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
+ TZ_MEM_PROTECT_REGION_ID), &desc);
+ }
+
+ if (ret) {
+ IPAERR("scm call SCM_SVC_MP failed: %d\n", ret);
+ kfree(ipa_tz_unlock_vec);
+ return -EFAULT;
+ }
+ kfree(ipa_tz_unlock_vec);
+
return 0;
}
@@ -4667,6 +4696,8 @@
ipa3_ctx->gsi_ch20_wa = resource_p->gsi_ch20_wa;
ipa3_ctx->use_ipa_pm = resource_p->use_ipa_pm;
ipa3_ctx->ipa3_active_clients_logging.log_rdy = false;
+ ipa3_ctx->mhi_evid_limits[0] = resource_p->mhi_evid_limits[0];
+ ipa3_ctx->mhi_evid_limits[1] = resource_p->mhi_evid_limits[1];
if (resource_p->ipa_tz_unlock_reg) {
ipa3_ctx->ipa_tz_unlock_reg_num =
resource_p->ipa_tz_unlock_reg_num;
@@ -4687,7 +4718,10 @@
}
/* unlock registers for uc */
- ipa3_tz_unlock_reg(ipa3_ctx);
+ result = ipa3_tz_unlock_reg(ipa3_ctx->ipa_tz_unlock_reg,
+ ipa3_ctx->ipa_tz_unlock_reg_num);
+ if (result)
+ IPAERR("Failed to unlock memory region using TZ\n");
/* default aggregation parameters */
ipa3_ctx->aggregation_type = IPA_MBIM_16;
@@ -5240,6 +5274,7 @@
struct resource *resource;
u32 *ipa_tz_unlock_reg;
int elem_num;
+ u32 mhi_evid_limits[2];
/* initialize ipa3_res */
ipa_drv_res->ipa_pipe_mem_start_ofst = IPA_PIPE_MEM_START_OFST;
@@ -5256,6 +5291,8 @@
ipa_drv_res->gsi_ch20_wa = false;
ipa_drv_res->ipa_tz_unlock_reg_num = 0;
ipa_drv_res->ipa_tz_unlock_reg = NULL;
+ ipa_drv_res->mhi_evid_limits[0] = IPA_MHI_GSI_EVENT_RING_ID_START;
+ ipa_drv_res->mhi_evid_limits[1] = IPA_MHI_GSI_EVENT_RING_ID_END;
/* Get IPA HW Version */
result = of_property_read_u32(pdev->dev.of_node, "qcom,ipa-hw-ver",
@@ -5432,6 +5469,34 @@
? "Needed" : "Not needed");
elem_num = of_property_count_elems_of_size(pdev->dev.of_node,
+ "qcom,mhi-event-ring-id-limits", sizeof(u32));
+
+ if (elem_num == 2) {
+ if (of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,mhi-event-ring-id-limits", mhi_evid_limits, 2)) {
+ IPAERR("failed to read mhi event ring id limits\n");
+ return -EFAULT;
+ }
+ if (mhi_evid_limits[0] > mhi_evid_limits[1]) {
+ IPAERR("mhi event ring id low limit > high limit\n");
+ return -EFAULT;
+ }
+ ipa_drv_res->mhi_evid_limits[0] = mhi_evid_limits[0];
+ ipa_drv_res->mhi_evid_limits[1] = mhi_evid_limits[1];
+ IPADBG(": mhi-event-ring-id-limits start=%u end=%u\n",
+ mhi_evid_limits[0], mhi_evid_limits[1]);
+ } else {
+ if (elem_num > 0) {
+ IPAERR("Invalid mhi event ring id limits number %d\n",
+ elem_num);
+ return -EINVAL;
+ }
+ IPADBG("use default mhi evt ring id limits start=%u end=%u\n",
+ ipa_drv_res->mhi_evid_limits[0],
+ ipa_drv_res->mhi_evid_limits[1]);
+ }
+
+ elem_num = of_property_count_elems_of_size(pdev->dev.of_node,
"qcom,ipa-tz-unlock-reg", sizeof(u32));
if (elem_num > 0 && elem_num % 2 == 0) {
@@ -5465,7 +5530,7 @@
ipa_tz_unlock_reg[pos++];
ipa_drv_res->ipa_tz_unlock_reg[i].size =
ipa_tz_unlock_reg[pos++];
- IPADBG("tz unlock reg %d: addr 0x%pa size %d\n", i,
+ IPADBG("tz unlock reg %d: addr 0x%pa size %llu\n", i,
&ipa_drv_res->ipa_tz_unlock_reg[i].reg_addr,
ipa_drv_res->ipa_tz_unlock_reg[i].size);
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 29fe24e..f22488a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1034,11 +1034,6 @@
void *user_data;
};
-struct ipa_tz_unlock_reg_info {
- u64 reg_addr;
- u32 size;
-};
-
struct ipa_dma_task_info {
struct ipa_mem_buffer mem;
struct ipahal_imm_cmd_pyld *cmd_pyld;
@@ -1191,6 +1186,7 @@
* @ipa_ready_cb_list: A list of all the clients who require a CB when IPA
* driver is ready/initialized.
* @init_completion_obj: Completion object to be used in case IPA driver hasn't
+ * @mhi_evid_limits: MHI event rings start and end ids
* finished initializing. Example of use - IOCTLs to /dev/ipa
* IPA context - holds all relevant info about IPA driver and its state
*/
@@ -1318,6 +1314,7 @@
struct completion init_completion_obj;
struct completion uc_loaded_completion_obj;
struct ipa3_smp2p_info smp2p_info;
+ u32 mhi_evid_limits[2]; /* start and end values */
u32 ipa_tz_unlock_reg_num;
struct ipa_tz_unlock_reg_info *ipa_tz_unlock_reg;
struct ipa_dma_task_info dma_task_info;
@@ -1351,6 +1348,7 @@
bool apply_rg10_wa;
bool gsi_ch20_wa;
bool tethered_flow_control;
+ u32 mhi_evid_limits[2]; /* start and end values */
u32 ipa_tz_unlock_reg_num;
struct ipa_tz_unlock_reg_info *ipa_tz_unlock_reg;
bool use_ipa_pm;
@@ -2249,4 +2247,5 @@
void ipa3_free_dma_task_for_gsi(void);
int ipa3_set_clock_plan_from_pm(int idx);
void __ipa_gsi_irq_rx_scedule_poll(struct ipa3_sys_context *sys);
+int ipa3_tz_unlock_reg(struct ipa_tz_unlock_reg_info *reg_info, u16 num_regs);
#endif /* _IPA3_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
index 08f2a8c..cb970ba 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
@@ -356,6 +356,14 @@
return -EINVAL;
}
+ if ((IPA_MHI_MAX_UL_CHANNELS + IPA_MHI_MAX_DL_CHANNELS) >
+ ((ipa3_ctx->mhi_evid_limits[1] -
+ ipa3_ctx->mhi_evid_limits[0]) + 1)) {
+ IPAERR("Not enough event rings for MHI\n");
+ ipa_assert();
+ return -EINVAL;
+ }
+
/* Initialize IPA MHI engine */
gsi_ep_info = ipa3_get_gsi_ep_info(IPA_CLIENT_MHI_PROD);
if (!gsi_ep_info) {
@@ -407,6 +415,8 @@
return -EINVAL;
}
+ in->start.gsi.evchid += ipa3_ctx->mhi_evid_limits[0];
+
client = in->sys->client;
ipa_ep_idx = ipa3_get_ep_mapping(client);
if (ipa_ep_idx == -1) {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index ae05880..fd38a2d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -4501,6 +4501,7 @@
api_ctrl->ipa_disconn_wdi3_pipes = ipa3_disconn_wdi3_pipes;
api_ctrl->ipa_enable_wdi3_pipes = ipa3_enable_wdi3_pipes;
api_ctrl->ipa_disable_wdi3_pipes = ipa3_disable_wdi3_pipes;
+ api_ctrl->ipa_tz_unlock_reg = ipa3_tz_unlock_reg;
return 0;
}
diff --git a/drivers/platform/msm/ipa/test/ipa_test_mhi.c b/drivers/platform/msm/ipa/test/ipa_test_mhi.c
index 78cdc50..98861de 100644
--- a/drivers/platform/msm/ipa/test/ipa_test_mhi.c
+++ b/drivers/platform/msm/ipa/test/ipa_test_mhi.c
@@ -1359,11 +1359,11 @@
IPA_UT_LOG("DB to event 0x%llx: base %pa ofst 0x%x\n",
p_events[event_ring_index].wp,
&(gsi_ctx->per.phys_addr), GSI_EE_n_EV_CH_k_DOORBELL_0_OFFS(
- event_ring_index + IPA_MHI_GSI_ER_START, 0));
+ event_ring_index + ipa3_ctx->mhi_evid_limits[0], 0));
iowrite32(p_events[event_ring_index].wp,
test_mhi_ctx->gsi_mmio +
GSI_EE_n_EV_CH_k_DOORBELL_0_OFFS(
- event_ring_index + IPA_MHI_GSI_ER_START, 0));
+ event_ring_index + ipa3_ctx->mhi_evid_limits[0], 0));
for (i = 0; i < buf_array_size; i++) {
/* calculate virtual pointer for current WP and RP */
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index d75f157..ec492af 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -4905,6 +4905,16 @@
if (of_have_populated_dt())
has_full_constraints = true;
+ /*
+ * Regulators may had failed to resolve their input supplies
+ * when were registered, either because the input supply was
+ * not registered yet or because its parent device was not
+ * bound yet. So attempt to resolve the input supplies for
+ * pending regulators before trying to disable unused ones.
+ */
+ class_for_each_device(®ulator_class, NULL, NULL,
+ regulator_register_resolve_supply);
+
/* If we have a full configuration then disable any regulators
* we have permission to change the status for and which are
* not in use or always_on. This is effectively the default
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c
index 375d818..d5f6fbf 100644
--- a/drivers/scsi/device_handler/scsi_dh_emc.c
+++ b/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -461,7 +461,7 @@
static int clariion_std_inquiry(struct scsi_device *sdev,
struct clariion_dh_data *csdev)
{
- int err;
+ int err = SCSI_DH_OK;
char *sp_model;
err = send_inquiry_cmd(sdev, 0, csdev);
diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c
index e734b8a..b986328 100644
--- a/drivers/soc/qcom/dcc_v2.c
+++ b/drivers/soc/qcom/dcc_v2.c
@@ -22,6 +22,7 @@
#include <linux/uaccess.h>
#include <soc/qcom/memory_dump.h>
#include <soc/qcom/scm.h>
+#include <dt-bindings/soc/qcom,dcc_v2.h>
#define TIMEOUT_US (100)
@@ -1088,14 +1089,30 @@
static DEVICE_ATTR(interrupt_disable, 0644,
dcc_show_interrupt_disable, dcc_store_interrupt_disable);
+static int dcc_add_loop(struct dcc_drvdata *drvdata, unsigned long loop_cnt)
+{
+ struct dcc_config_entry *entry;
+
+ entry = devm_kzalloc(drvdata->dev, sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ entry->loop_cnt = min_t(uint32_t, loop_cnt, MAX_LOOP_CNT);
+ entry->index = drvdata->nr_config[drvdata->curr_list]++;
+ entry->desc_type = DCC_LOOP_TYPE;
+ INIT_LIST_HEAD(&entry->list);
+ list_add_tail(&entry->list, &drvdata->cfg_head[drvdata->curr_list]);
+
+ return 0;
+}
+
static ssize_t dcc_store_loop(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
- int ret = size;
+ int ret;
unsigned long loop_cnt;
struct dcc_drvdata *drvdata = dev_get_drvdata(dev);
- struct dcc_config_entry *entry;
mutex_lock(&drvdata->mutex);
@@ -1110,18 +1127,12 @@
goto err;
}
- entry = devm_kzalloc(drvdata->dev, sizeof(*entry), GFP_KERNEL);
- if (!entry) {
- ret = -ENOMEM;
+ ret = dcc_add_loop(drvdata, loop_cnt);
+ if (ret)
goto err;
- }
- entry->loop_cnt = min_t(uint32_t, loop_cnt, MAX_LOOP_CNT);
- entry->index = drvdata->nr_config[drvdata->curr_list]++;
- entry->desc_type = DCC_LOOP_TYPE;
- INIT_LIST_HEAD(&entry->list);
- list_add_tail(&entry->list, &drvdata->cfg_head[drvdata->curr_list]);
-
+ mutex_unlock(&drvdata->mutex);
+ return size;
err:
mutex_unlock(&drvdata->mutex);
return ret;
@@ -1171,16 +1182,37 @@
}
static DEVICE_ATTR(rd_mod_wr, 0200, NULL, dcc_rd_mod_wr);
+static int dcc_add_write(struct dcc_drvdata *drvdata, unsigned int addr,
+ unsigned int write_val, int apb_bus)
+{
+ struct dcc_config_entry *entry;
+
+ entry = devm_kzalloc(drvdata->dev, sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ entry->desc_type = DCC_WRITE_TYPE;
+ entry->base = addr & BM(4, 31);
+ entry->offset = addr - entry->base;
+ entry->write_val = write_val;
+ entry->index = drvdata->nr_config[drvdata->curr_list]++;
+ entry->len = 1;
+ entry->apb_bus = apb_bus;
+ INIT_LIST_HEAD(&entry->list);
+ list_add_tail(&entry->list, &drvdata->cfg_head[drvdata->curr_list]);
+
+ return 0;
+}
+
static ssize_t dcc_write(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
- int ret = size;
+ int ret;
int nval;
unsigned int addr, write_val;
- int apb_bus;
+ int apb_bus = 0;
struct dcc_drvdata *drvdata = dev_get_drvdata(dev);
- struct dcc_config_entry *entry;
mutex_lock(&drvdata->mutex);
@@ -1197,23 +1229,15 @@
goto err;
}
- entry = devm_kzalloc(drvdata->dev, sizeof(*entry), GFP_KERNEL);
- if (!entry) {
- ret = -ENOMEM;
+ if (nval == 3 && apb_bus != 0)
+ apb_bus = 1;
+
+ ret = dcc_add_write(drvdata, addr, write_val, apb_bus);
+ if (ret)
goto err;
- }
- if (nval == 3)
- entry->apb_bus = true;
-
- entry->desc_type = DCC_WRITE_TYPE;
- entry->base = addr & BM(4, 31);
- entry->offset = addr - entry->base;
- entry->write_val = write_val;
- entry->index = drvdata->nr_config[drvdata->curr_list]++;
- entry->len = 1;
- INIT_LIST_HEAD(&entry->list);
- list_add_tail(&entry->list, &drvdata->cfg_head[drvdata->curr_list]);
+ mutex_unlock(&drvdata->mutex);
+ return size;
err:
mutex_unlock(&drvdata->mutex);
return ret;
@@ -1418,6 +1442,64 @@
dcc_sram_dev_deregister(drvdata);
}
+static void dcc_configure_list(struct dcc_drvdata *drvdata,
+ struct device_node *np)
+{
+ int ret, i;
+ const __be32 *prop;
+ uint32_t len, entry, val1, val2, apb_bus;
+ uint32_t curr_link_list;
+
+ ret = of_property_read_u32(np, "qcom,curr-link-list",
+ &curr_link_list);
+ if (ret)
+ return;
+
+ if (curr_link_list >= DCC_MAX_LINK_LIST) {
+ dev_err(drvdata->dev, "List configuration failed");
+ return;
+ }
+ drvdata->curr_list = curr_link_list;
+
+ prop = of_get_property(np, "qcom,link-list", &len);
+ if (prop) {
+ len /= sizeof(__be32);
+ i = 0;
+ while (i < len) {
+ entry = be32_to_cpu(prop[i++]);
+ val1 = be32_to_cpu(prop[i++]);
+ val2 = be32_to_cpu(prop[i++]);
+ apb_bus = be32_to_cpu(prop[i++]);
+
+ switch (entry) {
+ case DCC_READ:
+ ret = dcc_config_add(drvdata, val1,
+ val2, apb_bus);
+ break;
+ case DCC_WRITE:
+ ret = dcc_add_write(drvdata, val1,
+ val2, apb_bus);
+ break;
+ case DCC_LOOP:
+ ret = dcc_add_loop(drvdata, val1);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ if (ret) {
+ dev_err(drvdata->dev,
+ "DCC init time config failed err:%d\n",
+ ret);
+ break;
+ }
+ }
+
+ if (!ret)
+ dcc_enable(drvdata);
+ }
+}
+
static int dcc_probe(struct platform_device *pdev)
{
int ret, i;
@@ -1492,6 +1574,8 @@
if (ret)
goto err;
+ dcc_configure_list(drvdata, pdev->dev.of_node);
+
return 0;
err:
return ret;
@@ -1527,13 +1611,7 @@
{
return platform_driver_register(&dcc_driver);
}
-module_init(dcc_init);
-
-static void __exit dcc_exit(void)
-{
- platform_driver_unregister(&dcc_driver);
-}
-module_exit(dcc_exit);
+pure_initcall(dcc_init);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MSM data capture and compare engine");
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 04c611c..1794278 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -200,7 +200,6 @@
enum icnss_msa_perm {
ICNSS_MSA_PERM_HLOS_ALL = 0,
ICNSS_MSA_PERM_WLAN_HW_RW = 1,
- ICNSS_MSA_PERM_DUMP_COLLECT = 2,
ICNSS_MSA_PERM_MAX,
};
@@ -233,13 +232,6 @@
.nelems = 2,
},
- [ICNSS_MSA_PERM_DUMP_COLLECT] = {
- .vmids = {VMID_MSS_MSA, VMID_WLAN, VMID_HLOS},
- .perms = {PERM_READ | PERM_WRITE,
- PERM_READ | PERM_WRITE,
- PERM_READ},
- .nelems = 3,
- },
};
struct icnss_msa_perm_list_t msa_perm_list[ICNSS_MSA_PERM_MAX] = {
@@ -257,14 +249,6 @@
.nelems = 3,
},
- [ICNSS_MSA_PERM_DUMP_COLLECT] = {
- .vmids = {VMID_MSS_MSA, VMID_WLAN, VMID_WLAN_CE, VMID_HLOS},
- .perms = {PERM_READ | PERM_WRITE,
- PERM_READ | PERM_WRITE,
- PERM_READ | PERM_WRITE,
- PERM_READ},
- .nelems = 4,
- },
};
struct icnss_event_pd_service_down_data {
@@ -2491,9 +2475,10 @@
icnss_pr_vdbg("Modem-Notify: event %lu\n", code);
- if (code == SUBSYS_AFTER_SHUTDOWN) {
+ if (code == SUBSYS_AFTER_SHUTDOWN &&
+ notif->crashed != CRASH_STATUS_WDOG_BITE) {
ret = icnss_assign_msa_perm_all(priv,
- ICNSS_MSA_PERM_DUMP_COLLECT);
+ ICNSS_MSA_PERM_HLOS_ALL);
if (!ret) {
icnss_pr_info("Collecting msa0 segment dump\n");
icnss_msa0_ramdump(priv);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
index 6d459ef..f72eebc 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
@@ -106,8 +106,14 @@
g_virt_to_bus_offset = virt_to_dma(dev, (void *)0);
- (void)of_property_read_u32(dev->of_node, "cache-line-size",
+ err = of_property_read_u32(dev->of_node, "cache-line-size",
&g_cache_line_size);
+
+ if (err) {
+ dev_err(dev, "Missing cache-line-size property\n");
+ return -ENODEV;
+ }
+
g_fragments_size = 2 * g_cache_line_size;
/* Allocate space for the channels in coherent memory */
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c
index efc453e..ab92a1b 100644
--- a/drivers/target/iscsi/iscsi_target_erl0.c
+++ b/drivers/target/iscsi/iscsi_target_erl0.c
@@ -44,10 +44,8 @@
*/
if (cmd->unsolicited_data) {
cmd->seq_start_offset = cmd->write_data_done;
- cmd->seq_end_offset = (cmd->write_data_done +
- ((cmd->se_cmd.data_length >
- conn->sess->sess_ops->FirstBurstLength) ?
- conn->sess->sess_ops->FirstBurstLength : cmd->se_cmd.data_length));
+ cmd->seq_end_offset = min(cmd->se_cmd.data_length,
+ conn->sess->sess_ops->FirstBurstLength);
return;
}
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
index 4e603d0..59828d8 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -398,6 +398,12 @@
static struct uart_port *sunhv_port;
+void sunhv_migrate_hvcons_irq(int cpu)
+{
+ /* Migrate hvcons irq to param cpu */
+ irq_force_affinity(sunhv_port->irq, cpumask_of(cpu));
+}
+
/* Copy 's' into the con_write_page, decoding "\n" into
* "\r\n" along the way. We have to return two lengths
* because the caller needs to know how much to advance
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 9d247b8..f4f378c 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -950,9 +950,42 @@
if (!node) {
trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
+ /*
+ * USB Specification 2.0 Section 5.9.2 states that: "If
+ * there is only a single transaction in the microframe,
+ * only a DATA0 data packet PID is used. If there are
+ * two transactions per microframe, DATA1 is used for
+ * the first transaction data packet and DATA0 is used
+ * for the second transaction data packet. If there are
+ * three transactions per microframe, DATA2 is used for
+ * the first transaction data packet, DATA1 is used for
+ * the second, and DATA0 is used for the third."
+ *
+ * IOW, we should satisfy the following cases:
+ *
+ * 1) length <= maxpacket
+ * - DATA0
+ *
+ * 2) maxpacket < length <= (2 * maxpacket)
+ * - DATA1, DATA0
+ *
+ * 3) (2 * maxpacket) < length <= (3 * maxpacket)
+ * - DATA2, DATA1, DATA0
+ */
if (speed == USB_SPEED_HIGH) {
struct usb_ep *ep = &dep->endpoint;
- trb->size |= DWC3_TRB_SIZE_PCM1(ep->mult - 1);
+ unsigned int mult = ep->mult - 1;
+ unsigned int maxp;
+
+ maxp = usb_endpoint_maxp(ep->desc) & 0x07ff;
+
+ if (length <= (2 * maxp))
+ mult--;
+
+ if (length <= maxp)
+ mult--;
+
+ trb->size |= DWC3_TRB_SIZE_PCM1(mult);
}
} else {
trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS;
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index e32de9a..98509f2 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -2164,6 +2164,8 @@
static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
{
struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ struct usb_gadget_strings *gstr = cdev->driver->strings[0];
+ struct usb_string *dev_str = gstr->strings;
/* composite_disconnect() must already have been called
* by the underlying peripheral controller driver!
@@ -2183,6 +2185,9 @@
composite_dev_cleanup(cdev);
+ if (dev_str[USB_GADGET_MANUFACTURER_IDX].s == cdev->def_manufacturer)
+ dev_str[USB_GADGET_MANUFACTURER_IDX].s = "";
+
kfree(cdev->def_manufacturer);
kfree(cdev);
set_gadget_data(gadget, NULL);
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index d6e77a5..885ed26 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1179,11 +1179,12 @@
NULL
};
-int usb_os_desc_prepare_interf_dir(struct config_group *parent,
- int n_interf,
- struct usb_os_desc **desc,
- char **names,
- struct module *owner)
+struct config_group *usb_os_desc_prepare_interf_dir(
+ struct config_group *parent,
+ int n_interf,
+ struct usb_os_desc **desc,
+ char **names,
+ struct module *owner)
{
struct config_group *os_desc_group;
struct config_item_type *os_desc_type, *interface_type;
@@ -1195,7 +1196,7 @@
char *vlabuf = kzalloc(vla_group_size(data_chunk), GFP_KERNEL);
if (!vlabuf)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
os_desc_group = vla_ptr(vlabuf, data_chunk, os_desc_group);
os_desc_type = vla_ptr(vlabuf, data_chunk, os_desc_type);
@@ -1220,7 +1221,7 @@
configfs_add_default_group(&d->group, os_desc_group);
}
- return 0;
+ return os_desc_group;
}
EXPORT_SYMBOL(usb_os_desc_prepare_interf_dir);
diff --git a/drivers/usb/gadget/configfs.h b/drivers/usb/gadget/configfs.h
index 36c468c..540d5e9 100644
--- a/drivers/usb/gadget/configfs.h
+++ b/drivers/usb/gadget/configfs.h
@@ -5,11 +5,12 @@
void unregister_gadget_item(struct config_item *item);
-int usb_os_desc_prepare_interf_dir(struct config_group *parent,
- int n_interf,
- struct usb_os_desc **desc,
- char **names,
- struct module *owner);
+struct config_group *usb_os_desc_prepare_interf_dir(
+ struct config_group *parent,
+ int n_interf,
+ struct usb_os_desc **desc,
+ char **names,
+ struct module *owner);
static inline struct usb_os_desc *to_usb_os_desc(struct config_item *item)
{
diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c
index 1590927..9f7a29a 100644
--- a/drivers/usb/gadget/function/f_audio_source.c
+++ b/drivers/usb/gadget/function/f_audio_source.c
@@ -755,11 +755,11 @@
struct audio_dev *audio = substream->private_data;
unsigned long flags;
- spin_lock_irqsave(&audio->lock, flags);
-
/* Remove the QoS request */
pm_qos_remove_request(&audio->pm_qos);
+ spin_lock_irqsave(&audio->lock, flags);
+
audio->substream = NULL;
spin_unlock_irqrestore(&audio->lock, flags);
diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c
index 41e1b47..56a8e1b 100644
--- a/drivers/usb/gadget/function/f_rndis.c
+++ b/drivers/usb/gadget/function/f_rndis.c
@@ -920,6 +920,7 @@
free_netdev(opts->net);
}
+ kfree(opts->rndis_interf_group); /* single VLA chunk */
kfree(opts);
}
@@ -928,6 +929,7 @@
struct f_rndis_opts *opts;
struct usb_os_desc *descs[1];
char *names[1];
+ struct config_group *rndis_interf_group;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
@@ -948,8 +950,14 @@
names[0] = "rndis";
config_group_init_type_name(&opts->func_inst.group, "",
&rndis_func_type);
- usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
- names, THIS_MODULE);
+ rndis_interf_group =
+ usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
+ names, THIS_MODULE);
+ if (IS_ERR(rndis_interf_group)) {
+ rndis_free_inst(&opts->func_inst);
+ return ERR_CAST(rndis_interf_group);
+ }
+ opts->rndis_interf_group = rndis_interf_group;
return &opts->func_inst;
}
diff --git a/drivers/usb/gadget/function/u_rndis.h b/drivers/usb/gadget/function/u_rndis.h
index 4eafd50..4e2ad04 100644
--- a/drivers/usb/gadget/function/u_rndis.h
+++ b/drivers/usb/gadget/function/u_rndis.h
@@ -26,6 +26,7 @@
bool bound;
bool borrowed_net;
+ struct config_group *rndis_interf_group;
struct usb_os_desc rndis_os_desc;
char rndis_ext_compat_id[16];
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index fb17fb2..b62a3de 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -420,6 +420,7 @@
static void set_link_state(struct dummy_hcd *dum_hcd)
{
struct dummy *dum = dum_hcd->dum;
+ unsigned int power_bit;
dum_hcd->active = 0;
if (dum->pullup)
@@ -430,17 +431,19 @@
return;
set_link_state_by_speed(dum_hcd);
+ power_bit = (dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3 ?
+ USB_SS_PORT_STAT_POWER : USB_PORT_STAT_POWER);
if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0 ||
dum_hcd->active)
dum_hcd->resuming = 0;
/* Currently !connected or in reset */
- if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0 ||
+ if ((dum_hcd->port_status & power_bit) == 0 ||
(dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) {
- unsigned disconnect = USB_PORT_STAT_CONNECTION &
+ unsigned int disconnect = power_bit &
dum_hcd->old_status & (~dum_hcd->port_status);
- unsigned reset = USB_PORT_STAT_RESET &
+ unsigned int reset = USB_PORT_STAT_RESET &
(~dum_hcd->old_status) & dum_hcd->port_status;
/* Report reset and disconnect events to the driver */
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 8897195..6c6a3a8 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -860,9 +860,9 @@
fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
usbhs_pipe_running(pipe, 1);
- usbhsf_dma_start(pipe, fifo);
usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
dma_async_issue_pending(chan);
+ usbhsf_dma_start(pipe, fifo);
usbhs_pipe_enable(pipe);
xfer_work_end:
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index b6f1ade..76062ce 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -186,6 +186,7 @@
tty_kref_put(tty);
reset_open_count:
port->port.count = 0;
+ info->port = NULL;
usb_autopm_put_interface(serial->interface);
error_get_interface:
usb_serial_put(serial);
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 470b17b..11ee55e 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -171,6 +171,7 @@
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */
+ { USB_DEVICE(0x18EF, 0xE032) }, /* ELV TFD500 Data Logger */
{ USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
{ USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
{ USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 1939496..3249f42 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1015,6 +1015,8 @@
{ USB_DEVICE(WICED_VID, WICED_USB20706V2_PID) },
{ USB_DEVICE(TI_VID, TI_CC3200_LAUNCHPAD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_BT_USB_PID) },
+ { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_WL_USB_PID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 4fcf1ce..f9d15bd 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -610,6 +610,13 @@
#define ADI_GNICEPLUS_PID 0xF001
/*
+ * Cypress WICED USB UART
+ */
+#define CYPRESS_VID 0x04B4
+#define CYPRESS_WICED_BT_USB_PID 0x009B
+#define CYPRESS_WICED_WL_USB_PID 0xF900
+
+/*
* Microchip Technology, Inc.
*
* MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 2a99443..db3d34c 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -522,6 +522,7 @@
/* TP-LINK Incorporated products */
#define TPLINK_VENDOR_ID 0x2357
+#define TPLINK_PRODUCT_LTE 0x000D
#define TPLINK_PRODUCT_MA180 0x0201
/* Changhong products */
@@ -2011,6 +2012,7 @@
{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
{ USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600A) },
{ USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600E) },
+ { USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, TPLINK_PRODUCT_LTE, 0xff, 0x00, 0x00) }, /* TP-Link LTE Module */
{ USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE(TPLINK_VENDOR_ID, 0x9000), /* TP-Link MA260 */
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 652b433..e1c1e32 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -174,6 +174,10 @@
{DEVICE_SWI(0x413c, 0x81b3)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
{DEVICE_SWI(0x413c, 0x81b5)}, /* Dell Wireless 5811e QDL */
{DEVICE_SWI(0x413c, 0x81b6)}, /* Dell Wireless 5811e QDL */
+ {DEVICE_SWI(0x413c, 0x81cf)}, /* Dell Wireless 5819 */
+ {DEVICE_SWI(0x413c, 0x81d0)}, /* Dell Wireless 5819 */
+ {DEVICE_SWI(0x413c, 0x81d1)}, /* Dell Wireless 5818 */
+ {DEVICE_SWI(0x413c, 0x81d2)}, /* Dell Wireless 5818 */
/* Huawei devices */
{DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */
diff --git a/drivers/watchdog/kempld_wdt.c b/drivers/watchdog/kempld_wdt.c
index 8e302d0..3efa295 100644
--- a/drivers/watchdog/kempld_wdt.c
+++ b/drivers/watchdog/kempld_wdt.c
@@ -140,12 +140,19 @@
unsigned int timeout)
{
struct kempld_device_data *pld = wdt_data->pld;
- u32 prescaler = kempld_prescaler[PRESCALER_21];
+ u32 prescaler;
u64 stage_timeout64;
u32 stage_timeout;
u32 remainder;
u8 stage_cfg;
+#if GCC_VERSION < 40400
+ /* work around a bug compiling do_div() */
+ prescaler = READ_ONCE(kempld_prescaler[PRESCALER_21]);
+#else
+ prescaler = kempld_prescaler[PRESCALER_21];
+#endif
+
if (!stage)
return -EINVAL;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 07e46b7..cb936c9 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -450,10 +450,12 @@
set_page_writeback(page);
result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, true);
- if (result)
+ if (result) {
end_page_writeback(page);
- else
+ } else {
+ clean_page_buffers(page);
unlock_page(page);
+ }
blk_queue_exit(bdev->bd_queue);
return result;
}
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 71261b4..77f9efc 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -1680,6 +1680,9 @@
{
int ret;
+ if (ino == BTRFS_FIRST_FREE_OBJECTID)
+ return 1;
+
ret = get_cur_inode_state(sctx, ino, gen);
if (ret < 0)
goto out;
@@ -1865,7 +1868,7 @@
* not deleted and then re-created, if it was then we have no overwrite
* and we can just unlink this entry.
*/
- if (sctx->parent_root) {
+ if (sctx->parent_root && dir != BTRFS_FIRST_FREE_OBJECTID) {
ret = get_inode_info(sctx->parent_root, dir, NULL, &gen, NULL,
NULL, NULL, NULL);
if (ret < 0 && ret != -ENOENT)
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 953275b..4a6df2c 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1323,8 +1323,8 @@
ceph_dir_clear_ordered(dir);
dout("d_delete %p\n", dn);
d_delete(dn);
- } else {
- if (have_lease && d_unhashed(dn))
+ } else if (have_lease) {
+ if (d_unhashed(dn))
d_add(dn, NULL);
update_dentry_lease(dn, rinfo->dlease,
session,
diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c
index 7d752d5..4c9c72f 100644
--- a/fs/ceph/ioctl.c
+++ b/fs/ceph/ioctl.c
@@ -25,7 +25,7 @@
l.stripe_count = ci->i_layout.stripe_count;
l.object_size = ci->i_layout.object_size;
l.data_pool = ci->i_layout.pool_id;
- l.preferred_osd = (s32)-1;
+ l.preferred_osd = -1;
if (copy_to_user(arg, &l, sizeof(l)))
return -EFAULT;
}
@@ -97,7 +97,7 @@
nl.data_pool = ci->i_layout.pool_id;
/* this is obsolete, and always -1 */
- nl.preferred_osd = le64_to_cpu(-1);
+ nl.preferred_osd = -1;
err = __validate_layout(mdsc, &nl);
if (err)
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index e3e1a80..c0f52c4 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1782,13 +1782,18 @@
int *pfreepath)
{
char *path;
+ struct inode *dir;
- if (ceph_snap(d_inode(dentry->d_parent)) == CEPH_NOSNAP) {
- *pino = ceph_ino(d_inode(dentry->d_parent));
+ rcu_read_lock();
+ dir = d_inode_rcu(dentry->d_parent);
+ if (dir && ceph_snap(dir) == CEPH_NOSNAP) {
+ *pino = ceph_ino(dir);
+ rcu_read_unlock();
*ppath = dentry->d_name.name;
*ppathlen = dentry->d_name.len;
return 0;
}
+ rcu_read_unlock();
path = ceph_mdsc_build_path(dentry, ppathlen, pino, 1);
if (IS_ERR(path))
return PTR_ERR(path);
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 48ef401..7b496a4 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -365,6 +365,8 @@
unsigned int (*calc_smb_size)(void *);
/* check for STATUS_PENDING and process it in a positive case */
bool (*is_status_pending)(char *, struct TCP_Server_Info *, int);
+ /* check for STATUS_NETWORK_SESSION_EXPIRED */
+ bool (*is_session_expired)(char *);
/* send oplock break response */
int (*oplock_response)(struct cifs_tcon *, struct cifs_fid *,
struct cifsInodeInfo *);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 1f91c9d..cc420d6 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1457,6 +1457,13 @@
return length;
server->total_read += length;
+ if (server->ops->is_session_expired &&
+ server->ops->is_session_expired(buf)) {
+ cifs_reconnect(server);
+ wake_up(&server->response_q);
+ return -1;
+ }
+
if (server->ops->is_status_pending &&
server->ops->is_status_pending(buf, server, 0)) {
discard_remaining_data(server);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index f6712b6..580b3a4 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -796,6 +796,13 @@
cifs_dump_mem("Bad SMB: ", buf,
min_t(unsigned int, server->total_read, 48));
+ if (server->ops->is_session_expired &&
+ server->ops->is_session_expired(buf)) {
+ cifs_reconnect(server);
+ wake_up(&server->response_q);
+ return -1;
+ }
+
if (server->ops->is_status_pending &&
server->ops->is_status_pending(buf, server, length))
return -1;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index b696824..812e488 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1018,6 +1018,18 @@
return true;
}
+static bool
+smb2_is_session_expired(char *buf)
+{
+ struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
+
+ if (hdr->Status != STATUS_NETWORK_SESSION_EXPIRED)
+ return false;
+
+ cifs_dbg(FYI, "Session expired\n");
+ return true;
+}
+
static int
smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
struct cifsInodeInfo *cinode)
@@ -1609,6 +1621,7 @@
.close_dir = smb2_close_dir,
.calc_smb_size = smb2_calc_size,
.is_status_pending = smb2_is_status_pending,
+ .is_session_expired = smb2_is_session_expired,
.oplock_response = smb2_oplock_response,
.queryfs = smb2_queryfs,
.mand_lock = smb2_mand_lock,
@@ -1690,6 +1703,7 @@
.close_dir = smb2_close_dir,
.calc_smb_size = smb2_calc_size,
.is_status_pending = smb2_is_status_pending,
+ .is_session_expired = smb2_is_session_expired,
.oplock_response = smb2_oplock_response,
.queryfs = smb2_queryfs,
.mand_lock = smb2_mand_lock,
@@ -1773,6 +1787,7 @@
.close_dir = smb2_close_dir,
.calc_smb_size = smb2_calc_size,
.is_status_pending = smb2_is_status_pending,
+ .is_session_expired = smb2_is_session_expired,
.oplock_response = smb2_oplock_response,
.queryfs = smb2_queryfs,
.mand_lock = smb2_mand_lock,
@@ -1862,6 +1877,7 @@
.close_dir = smb2_close_dir,
.calc_smb_size = smb2_calc_size,
.is_status_pending = smb2_is_status_pending,
+ .is_session_expired = smb2_is_session_expired,
.oplock_response = smb2_oplock_response,
.queryfs = smb2_queryfs,
.mand_lock = smb2_mand_lock,
diff --git a/fs/direct-io.c b/fs/direct-io.c
index c60756e..c6220a2 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -835,7 +835,8 @@
*/
if (sdio->boundary) {
ret = dio_send_cur_page(dio, sdio, map_bh);
- dio_bio_submit(dio, sdio);
+ if (sdio->bio)
+ dio_bio_submit(dio, sdio);
put_page(sdio->cur_page);
sdio->cur_page = NULL;
}
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index d17d12e..510e664 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -527,7 +527,7 @@
inode_lock(inode);
isize = i_size_read(inode);
- if (offset >= isize) {
+ if (offset < 0 || offset >= isize) {
inode_unlock(inode);
return -ENXIO;
}
@@ -590,7 +590,7 @@
inode_lock(inode);
isize = i_size_read(inode);
- if (offset >= isize) {
+ if (offset < 0 || offset >= isize) {
inode_unlock(inode);
return -ENXIO;
}
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 2c5ae0b..08b3f62 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1630,7 +1630,12 @@
goto fail;
}
repeat:
- page = grab_cache_page_write_begin(mapping, index, flags);
+ /*
+ * Do not use grab_cache_page_write_begin() to avoid deadlock due to
+ * wait_for_stable_page. Will wait that below with our IO control.
+ */
+ page = pagecache_get_page(mapping, index,
+ FGP_LOCK | FGP_WRITE | FGP_CREAT, GFP_NOFS);
if (!page) {
err = -ENOMEM;
goto fail;
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 74a2b44..e10f616 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -1263,7 +1263,7 @@
struct curseg_info *curseg = CURSEG_I(sbi, type);
const struct victim_selection *v_ops = DIRTY_I(sbi)->v_ops;
- if (IS_NODESEG(type) || !has_not_enough_free_secs(sbi, 0, 0))
+ if (IS_NODESEG(type))
return v_ops->get_victim(sbi,
&(curseg)->next_segno, BG_GC, type, SSR);
diff --git a/fs/mpage.c b/fs/mpage.c
index 1193d43..d4e17c8 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -502,6 +502,16 @@
try_to_free_buffers(page);
}
+/*
+ * For situations where we want to clean all buffers attached to a page.
+ * We don't need to calculate how many buffers are attached to the page,
+ * we just need to specify a number larger than the maximum number of buffers.
+ */
+void clean_page_buffers(struct page *page)
+{
+ clean_buffers(page, ~0U);
+}
+
static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
void *data)
{
@@ -640,10 +650,8 @@
if (bio == NULL) {
if (first_unmapped == blocks_per_page) {
if (!bdev_write_page(bdev, blocks[0] << (blkbits - 9),
- page, wbc)) {
- clean_buffers(page, first_unmapped);
+ page, wbc))
goto out;
- }
}
bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9),
BIO_MAX_PAGES, GFP_NOFS|__GFP_HIGH);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 211dc2a..3069cd4 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -753,6 +753,14 @@
return 0;
}
+void cleanup_callback_cred(void)
+{
+ if (callback_cred) {
+ put_rpccred(callback_cred);
+ callback_cred = NULL;
+ }
+}
+
static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses)
{
if (clp->cl_minorversion == 0) {
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index a0dee8a..d35eb07 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -7012,23 +7012,24 @@
ret = set_callback_cred();
if (ret)
- return -ENOMEM;
+ return ret;
+
laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
if (laundry_wq == NULL) {
ret = -ENOMEM;
- goto out_recovery;
+ goto out_cleanup_cred;
}
ret = nfsd4_create_callback_queue();
if (ret)
goto out_free_laundry;
set_max_delegations();
-
return 0;
out_free_laundry:
destroy_workqueue(laundry_wq);
-out_recovery:
+out_cleanup_cred:
+ cleanup_callback_cred();
return ret;
}
@@ -7086,6 +7087,7 @@
{
destroy_workqueue(laundry_wq);
nfsd4_destroy_callback_queue();
+ cleanup_callback_cred();
}
static void
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 4516e8b..005c911 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -615,6 +615,7 @@
extern __be32 nfs4_check_open_reclaim(clientid_t *clid,
struct nfsd4_compound_state *cstate, struct nfsd_net *nn);
extern int set_callback_cred(void);
+extern void cleanup_callback_cred(void);
extern void nfsd4_probe_callback(struct nfs4_client *clp);
extern void nfsd4_probe_callback_sync(struct nfs4_client *clp);
extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 77d1632..8dce409 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -532,6 +532,7 @@
init_waitqueue_head(&res->l_event);
INIT_LIST_HEAD(&res->l_blocked_list);
INIT_LIST_HEAD(&res->l_mask_waiters);
+ INIT_LIST_HEAD(&res->l_holders);
}
void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,
@@ -749,6 +750,50 @@
res->l_flags = 0UL;
}
+/*
+ * Keep a list of processes who have interest in a lockres.
+ * Note: this is now only uesed for check recursive cluster locking.
+ */
+static inline void ocfs2_add_holder(struct ocfs2_lock_res *lockres,
+ struct ocfs2_lock_holder *oh)
+{
+ INIT_LIST_HEAD(&oh->oh_list);
+ oh->oh_owner_pid = get_pid(task_pid(current));
+
+ spin_lock(&lockres->l_lock);
+ list_add_tail(&oh->oh_list, &lockres->l_holders);
+ spin_unlock(&lockres->l_lock);
+}
+
+static inline void ocfs2_remove_holder(struct ocfs2_lock_res *lockres,
+ struct ocfs2_lock_holder *oh)
+{
+ spin_lock(&lockres->l_lock);
+ list_del(&oh->oh_list);
+ spin_unlock(&lockres->l_lock);
+
+ put_pid(oh->oh_owner_pid);
+}
+
+static inline int ocfs2_is_locked_by_me(struct ocfs2_lock_res *lockres)
+{
+ struct ocfs2_lock_holder *oh;
+ struct pid *pid;
+
+ /* look in the list of holders for one with the current task as owner */
+ spin_lock(&lockres->l_lock);
+ pid = task_pid(current);
+ list_for_each_entry(oh, &lockres->l_holders, oh_list) {
+ if (oh->oh_owner_pid == pid) {
+ spin_unlock(&lockres->l_lock);
+ return 1;
+ }
+ }
+ spin_unlock(&lockres->l_lock);
+
+ return 0;
+}
+
static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres,
int level)
{
@@ -2333,8 +2378,9 @@
goto getbh;
}
- if (ocfs2_mount_local(osb))
- goto local;
+ if ((arg_flags & OCFS2_META_LOCK_GETBH) ||
+ ocfs2_mount_local(osb))
+ goto update;
if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
ocfs2_wait_for_recovery(osb);
@@ -2363,7 +2409,7 @@
if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
ocfs2_wait_for_recovery(osb);
-local:
+update:
/*
* We only see this flag if we're being called from
* ocfs2_read_locked_inode(). It means we're locking an inode
@@ -2497,6 +2543,59 @@
ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
}
+/*
+ * This _tracker variantes are introduced to deal with the recursive cluster
+ * locking issue. The idea is to keep track of a lock holder on the stack of
+ * the current process. If there's a lock holder on the stack, we know the
+ * task context is already protected by cluster locking. Currently, they're
+ * used in some VFS entry routines.
+ *
+ * return < 0 on error, return == 0 if there's no lock holder on the stack
+ * before this call, return == 1 if this call would be a recursive locking.
+ */
+int ocfs2_inode_lock_tracker(struct inode *inode,
+ struct buffer_head **ret_bh,
+ int ex,
+ struct ocfs2_lock_holder *oh)
+{
+ int status;
+ int arg_flags = 0, has_locked;
+ struct ocfs2_lock_res *lockres;
+
+ lockres = &OCFS2_I(inode)->ip_inode_lockres;
+ has_locked = ocfs2_is_locked_by_me(lockres);
+ /* Just get buffer head if the cluster lock has been taken */
+ if (has_locked)
+ arg_flags = OCFS2_META_LOCK_GETBH;
+
+ if (likely(!has_locked || ret_bh)) {
+ status = ocfs2_inode_lock_full(inode, ret_bh, ex, arg_flags);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ return status;
+ }
+ }
+ if (!has_locked)
+ ocfs2_add_holder(lockres, oh);
+
+ return has_locked;
+}
+
+void ocfs2_inode_unlock_tracker(struct inode *inode,
+ int ex,
+ struct ocfs2_lock_holder *oh,
+ int had_lock)
+{
+ struct ocfs2_lock_res *lockres;
+
+ lockres = &OCFS2_I(inode)->ip_inode_lockres;
+ if (!had_lock) {
+ ocfs2_remove_holder(lockres, oh);
+ ocfs2_inode_unlock(inode, ex);
+ }
+}
+
int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno)
{
struct ocfs2_lock_res *lockres;
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
index d293a22..a7fc18b 100644
--- a/fs/ocfs2/dlmglue.h
+++ b/fs/ocfs2/dlmglue.h
@@ -70,6 +70,11 @@
__be32 lvb_os_seqno;
};
+struct ocfs2_lock_holder {
+ struct list_head oh_list;
+ struct pid *oh_owner_pid;
+};
+
/* ocfs2_inode_lock_full() 'arg_flags' flags */
/* don't wait on recovery. */
#define OCFS2_META_LOCK_RECOVERY (0x01)
@@ -77,6 +82,8 @@
#define OCFS2_META_LOCK_NOQUEUE (0x02)
/* don't block waiting for the downconvert thread, instead return -EAGAIN */
#define OCFS2_LOCK_NONBLOCK (0x04)
+/* just get back disk inode bh if we've got cluster lock. */
+#define OCFS2_META_LOCK_GETBH (0x08)
/* Locking subclasses of inode cluster lock */
enum {
@@ -170,4 +177,15 @@
/* To set the locking protocol on module initialization */
void ocfs2_set_locking_protocol(void);
+
+/* The _tracker pair is used to avoid cluster recursive locking */
+int ocfs2_inode_lock_tracker(struct inode *inode,
+ struct buffer_head **ret_bh,
+ int ex,
+ struct ocfs2_lock_holder *oh);
+void ocfs2_inode_unlock_tracker(struct inode *inode,
+ int ex,
+ struct ocfs2_lock_holder *oh,
+ int had_lock);
+
#endif /* DLMGLUE_H */
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index e63af7d..594575e 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -172,6 +172,7 @@
struct list_head l_blocked_list;
struct list_head l_mask_waiters;
+ struct list_head l_holders;
unsigned long l_flags;
char l_name[OCFS2_LOCK_ID_MAX_LEN];
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 18f7612..1370a4e 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2896,6 +2896,52 @@
}
#endif /* CONFIG_TASK_IO_ACCOUNTING */
+#ifdef CONFIG_DETECT_HUNG_TASK
+static ssize_t proc_hung_task_detection_enabled_read(struct file *file,
+ char __user *buf, size_t count, loff_t *ppos)
+{
+ struct task_struct *task = get_proc_task(file_inode(file));
+ char buffer[PROC_NUMBUF];
+ size_t len;
+ bool hang_detection_enabled;
+
+ if (!task)
+ return -ESRCH;
+ hang_detection_enabled = task->hang_detection_enabled;
+ put_task_struct(task);
+
+ len = snprintf(buffer, sizeof(buffer), "%d\n", hang_detection_enabled);
+
+ return simple_read_from_buffer(buf, sizeof(buffer), ppos, buffer, len);
+}
+
+static ssize_t proc_hung_task_detection_enabled_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos)
+{
+ struct task_struct *task;
+ bool hang_detection_enabled;
+ int rv;
+
+ rv = kstrtobool_from_user(buf, count, &hang_detection_enabled);
+ if (rv < 0)
+ return rv;
+
+ task = get_proc_task(file_inode(file));
+ if (!task)
+ return -ESRCH;
+ task->hang_detection_enabled = hang_detection_enabled;
+ put_task_struct(task);
+
+ return count;
+}
+
+static const struct file_operations proc_hung_task_detection_enabled_operations = {
+ .read = proc_hung_task_detection_enabled_read,
+ .write = proc_hung_task_detection_enabled_write,
+ .llseek = generic_file_llseek,
+};
+#endif
+
#ifdef CONFIG_USER_NS
static int proc_id_map_open(struct inode *inode, struct file *file,
const struct seq_operations *seq_ops)
@@ -3138,6 +3184,10 @@
#ifdef CONFIG_HARDWALL
ONE("hardwall", S_IRUGO, proc_pid_hardwall),
#endif
+#ifdef CONFIG_DETECT_HUNG_TASK
+ REG("hang_detection_enabled", 0666,
+ proc_hung_task_detection_enabled_operations),
+#endif
#ifdef CONFIG_USER_NS
REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations),
REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
@@ -3526,6 +3576,10 @@
#ifdef CONFIG_HARDWALL
ONE("hardwall", S_IRUGO, proc_pid_hardwall),
#endif
+#ifdef CONFIG_DETECT_HUNG_TASK
+ REG("hang_detection_enabled", 0666,
+ proc_hung_task_detection_enabled_operations),
+#endif
#ifdef CONFIG_USER_NS
REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations),
REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
diff --git a/include/dt-bindings/soc/qcom,dcc_v2.h b/include/dt-bindings/soc/qcom,dcc_v2.h
new file mode 100644
index 0000000..fb4ed6d
--- /dev/null
+++ b/include/dt-bindings/soc/qcom,dcc_v2.h
@@ -0,0 +1,20 @@
+/* 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.
+ */
+
+#ifndef __DT_BINDINGS_QCOM_DCC_V2_H
+#define __DT_BINDINGS_QCOM_DCC_V2_H
+
+#define DCC_READ 0
+#define DCC_WRITE 1
+#define DCC_LOOP 2
+
+#endif
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index ebbacd1..447a915 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -226,6 +226,7 @@
loff_t, unsigned, unsigned,
struct page *, void *);
void page_zero_new_buffers(struct page *page, unsigned from, unsigned to);
+void clean_page_buffers(struct page *page);
int cont_write_begin(struct file *, struct address_space *, loff_t,
unsigned, unsigned, struct page **, void **,
get_block_t *, loff_t *);
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index f8e7e8c..02736245 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -1165,6 +1165,16 @@
int ee;
};
+/**
+ * struct ipa_tz_unlock_reg_info - Used in order unlock regions of memory by TZ
+ * @reg_addr - Physical address of the start of the region
+ * @size - Size of the region in bytes
+ */
+struct ipa_tz_unlock_reg_info {
+ u64 reg_addr;
+ u64 size;
+};
+
#if defined CONFIG_IPA || defined CONFIG_IPA3
/*
@@ -1530,6 +1540,21 @@
int ipa_register_ipa_ready_cb(void (*ipa_ready_cb)(void *user_data),
void *user_data);
+/**
+ * ipa_tz_unlock_reg - Unlocks memory regions so that they become accessible
+ * from AP.
+ * @reg_info - Pointer to array of memory regions to unlock
+ * @num_regs - Number of elements in the array
+ *
+ * Converts the input array of regions to a struct that TZ understands and
+ * issues an SCM call.
+ * Also flushes the memory cache to DDR in order to make sure that TZ sees the
+ * correct data structure.
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa_tz_unlock_reg(struct ipa_tz_unlock_reg_info *reg_info, u16 num_regs);
+
#else /* (CONFIG_IPA || CONFIG_IPA3) */
/*
@@ -2276,6 +2301,12 @@
return -EPERM;
}
+static inline int ipa_tz_unlock_reg(struct ipa_tz_unlock_reg_info *reg_info,
+ u16 num_regs)
+{
+ return -EPERM;
+}
+
#endif /* (CONFIG_IPA || CONFIG_IPA3) */
#endif /* _IPA_H_ */
diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h
index ebca446..6e0b439 100644
--- a/include/linux/msm_gsi.h
+++ b/include/linux/msm_gsi.h
@@ -82,6 +82,8 @@
* @irq: IRQ number
* @phys_addr: physical address of GSI block
* @size: register size of GSI block
+ * @mhi_er_id_limits_valid: valid flag for mhi_er_id_limits
+ * @mhi_er_id_limits: MHI event ring start and end ids
* @notify_cb: general notification callback
* @req_clk_cb: callback to request peripheral clock
* granted should be set to true if request is completed
@@ -105,6 +107,8 @@
unsigned int irq;
phys_addr_t phys_addr;
unsigned long size;
+ bool mhi_er_id_limits_valid;
+ uint32_t mhi_er_id_limits[2];
void (*notify_cb)(struct gsi_per_notify *notify);
void (*req_clk_cb)(void *user_data, bool *granted);
int (*rel_clk_cb)(void *user_data);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 67860f3..b7ff73d 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1946,6 +1946,7 @@
#ifdef CONFIG_DETECT_HUNG_TASK
/* hung task detection */
unsigned long last_switch_count;
+ bool hang_detection_enabled;
#endif
/* filesystem information */
struct fs_struct *fs;
diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h
index 3597d55..12bd032 100644
--- a/include/linux/sched/sysctl.h
+++ b/include/linux/sched/sysctl.h
@@ -6,6 +6,7 @@
extern unsigned int sysctl_hung_task_panic;
extern unsigned long sysctl_hung_task_timeout_secs;
extern int sysctl_hung_task_warnings;
+extern int sysctl_hung_task_selective_monitoring;
extern int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
void __user *buffer,
size_t *lenp, loff_t *ppos);
diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h
index a03acd0..695257a 100644
--- a/include/sound/seq_virmidi.h
+++ b/include/sound/seq_virmidi.h
@@ -60,6 +60,7 @@
int port; /* created/attached port */
unsigned int flags; /* SNDRV_VIRMIDI_* */
rwlock_t filelist_lock;
+ struct rw_semaphore filelist_sem;
struct list_head filelist;
};
diff --git a/include/uapi/linux/esoc_ctrl.h b/include/uapi/linux/esoc_ctrl.h
index 4201c95..e2bd12b 100644
--- a/include/uapi/linux/esoc_ctrl.h
+++ b/include/uapi/linux/esoc_ctrl.h
@@ -9,6 +9,7 @@
#define ESOC_WAIT_FOR_REQ _IOR(ESOC_CODE, 2, unsigned int)
#define ESOC_NOTIFY _IOW(ESOC_CODE, 3, unsigned int)
#define ESOC_GET_STATUS _IOR(ESOC_CODE, 4, unsigned int)
+#define ESOC_GET_ERR_FATAL _IOR(ESOC_CODE, 5, unsigned int)
#define ESOC_WAIT_FOR_CRASH _IOR(ESOC_CODE, 6, unsigned int)
#define ESOC_REG_REQ_ENG _IO(ESOC_CODE, 7)
#define ESOC_REG_CMD_ENG _IO(ESOC_CODE, 8)
diff --git a/include/uapi/linux/mroute6.h b/include/uapi/linux/mroute6.h
index 5062fb5..ed57211 100644
--- a/include/uapi/linux/mroute6.h
+++ b/include/uapi/linux/mroute6.h
@@ -4,6 +4,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sockios.h>
+#include <linux/in6.h> /* For struct sockaddr_in6. */
/*
* Based on the MROUTING 3.5 defines primarily to keep
diff --git a/include/uapi/linux/rds.h b/include/uapi/linux/rds.h
index 0f9265c..7af20a1 100644
--- a/include/uapi/linux/rds.h
+++ b/include/uapi/linux/rds.h
@@ -35,6 +35,7 @@
#define _LINUX_RDS_H
#include <linux/types.h>
+#include <linux/socket.h> /* For __kernel_sockaddr_storage. */
#define RDS_IB_ABI_VERSION 0x301
@@ -223,7 +224,7 @@
};
struct rds_get_mr_for_dest_args {
- struct sockaddr_storage dest_addr;
+ struct __kernel_sockaddr_storage dest_addr;
struct rds_iovec vec;
uint64_t cookie_addr;
uint64_t flags;
diff --git a/init/initramfs.c b/init/initramfs.c
index f8ce812..d0b53f49 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -19,6 +19,7 @@
#include <linux/syscalls.h>
#include <linux/utime.h>
#include <linux/initramfs.h>
+#include <linux/file.h>
static ssize_t __init xwrite(int fd, const char *p, size_t count)
{
@@ -664,6 +665,7 @@
printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
free_initrd();
#endif
+ flush_delayed_fput();
/*
* Try loading default modules from initramfs. This gives
* us a chance to load before device_initcalls.
diff --git a/init/main.c b/init/main.c
index aca8f3e..674bc77 100644
--- a/init/main.c
+++ b/init/main.c
@@ -70,7 +70,6 @@
#include <linux/shmem_fs.h>
#include <linux/slab.h>
#include <linux/perf_event.h>
-#include <linux/file.h>
#include <linux/ptrace.h>
#include <linux/blkdev.h>
#include <linux/elevator.h>
@@ -946,8 +945,6 @@
system_state = SYSTEM_RUNNING;
numa_default_policy();
- flush_delayed_fput();
-
rcu_end_inkernel_boot();
if (ramdisk_execute_command) {
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index 2b59c82..b94d3d1 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -17,6 +17,7 @@
#include <linux/sysctl.h>
#include <linux/utsname.h>
#include <trace/events/sched.h>
+#include <linux/sched/sysctl.h>
/*
* The number of tasks checked:
@@ -24,6 +25,14 @@
int __read_mostly sysctl_hung_task_check_count = PID_MAX_LIMIT;
/*
+ * Selective monitoring of hung tasks.
+ *
+ * if set to 1, khungtaskd skips monitoring tasks, which has
+ * task_struct->hang_detection_enabled value not set, else monitors all tasks.
+ */
+int sysctl_hung_task_selective_monitoring = 1;
+
+/*
* Limit number of tasks checked in a batch.
*
* This value controls the preemptibility of khungtaskd since preemption
@@ -179,7 +188,10 @@
}
/* use "==" to skip the TASK_KILLABLE tasks waiting on NFS */
if (t->state == TASK_UNINTERRUPTIBLE)
- check_hung_task(t, timeout);
+ /* Check for selective monitoring */
+ if (!sysctl_hung_task_selective_monitoring ||
+ t->hang_detection_enabled)
+ check_hung_task(t, timeout);
}
unlock:
rcu_read_unlock();
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 4d7ffc0..6599c7f 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -3260,10 +3260,17 @@
if (depth) {
hlock = curr->held_locks + depth - 1;
if (hlock->class_idx == class_idx && nest_lock) {
- if (hlock->references)
+ if (hlock->references) {
+ /*
+ * Check: unsigned int references:12, overflow.
+ */
+ if (DEBUG_LOCKS_WARN_ON(hlock->references == (1 << 12)-1))
+ return 0;
+
hlock->references++;
- else
+ } else {
hlock->references = 2;
+ }
return 1;
}
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 4f8f9c1..084c41c 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -792,8 +792,13 @@
long long oldval;
struct rcu_dynticks *rdtp;
- RCU_LOCKDEP_WARN(!irqs_disabled(), "rcu_irq_exit() invoked with irqs enabled!!!");
rdtp = this_cpu_ptr(&rcu_dynticks);
+
+ /* Page faults can happen in NMI handlers, so check... */
+ if (READ_ONCE(rdtp->dynticks_nmi_nesting))
+ return;
+
+ RCU_LOCKDEP_WARN(!irqs_disabled(), "rcu_irq_exit() invoked with irqs enabled!!!");
oldval = rdtp->dynticks_nesting;
rdtp->dynticks_nesting--;
WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
@@ -930,8 +935,13 @@
struct rcu_dynticks *rdtp;
long long oldval;
- RCU_LOCKDEP_WARN(!irqs_disabled(), "rcu_irq_enter() invoked with irqs enabled!!!");
rdtp = this_cpu_ptr(&rcu_dynticks);
+
+ /* Page faults can happen in NMI handlers, so check... */
+ if (READ_ONCE(rdtp->dynticks_nmi_nesting))
+ return;
+
+ RCU_LOCKDEP_WARN(!irqs_disabled(), "rcu_irq_enter() invoked with irqs enabled!!!");
oldval = rdtp->dynticks_nesting;
rdtp->dynticks_nesting++;
WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index ae0c347..01a589c 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1169,6 +1169,7 @@
cpumask_t allowed_mask;
rq = task_rq_lock(p, &rf);
+ update_rq_clock(rq);
if (p->flags & PF_KTHREAD) {
/*
diff --git a/kernel/sched/core_ctl.c b/kernel/sched/core_ctl.c
index f95243b..cc5a97c 100644
--- a/kernel/sched/core_ctl.c
+++ b/kernel/sched/core_ctl.c
@@ -38,6 +38,7 @@
unsigned int active_cpus;
unsigned int num_cpus;
unsigned int nr_isolated_cpus;
+ unsigned int nr_not_preferred_cpus;
#ifdef CONFIG_SCHED_CORE_ROTATE
unsigned long set_max;
unsigned long set_cur;
@@ -350,6 +351,7 @@
unsigned int val[MAX_CPUS_PER_CLUSTER];
unsigned long flags;
int ret;
+ int not_preferred_count = 0;
ret = sscanf(buf, "%u %u %u %u %u %u\n",
&val[0], &val[1], &val[2], &val[3],
@@ -361,7 +363,9 @@
for (i = 0; i < state->num_cpus; i++) {
c = &per_cpu(cpu_state, i + state->first_cpu);
c->not_preferred = val[i];
+ not_preferred_count += !!val[i];
}
+ state->nr_not_preferred_cpus = not_preferred_count;
spin_unlock_irqrestore(&state_lock, flags);
return count;
@@ -793,10 +797,18 @@
continue;
if (cluster->active_cpus == need)
break;
- /* Don't offline busy CPUs. */
+ /* Don't isolate busy CPUs. */
if (c->is_busy)
continue;
+ /*
+ * We isolate only the not_preferred CPUs. If none
+ * of the CPUs are selected as not_preferred, then
+ * all CPUs are eligible for isolation.
+ */
+ if (cluster->nr_not_preferred_cpus && !c->not_preferred)
+ continue;
+
if (!should_we_isolate(c->cpu, cluster))
continue;
@@ -1109,6 +1121,7 @@
cluster->set_cur = cluster->set_max - 1;
#endif
cluster->enable = true;
+ cluster->nr_not_preferred_cpus = 0;
INIT_LIST_HEAD(&cluster->lru);
spin_lock_init(&cluster->pending_lock);
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 7feba85..1bf8e63 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -914,15 +914,30 @@
char *pos = buf;
char *end = buf + sizeof(buf);
int idx;
+ struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq);
pos += snprintf(pos, sizeof(buf),
- "sched: RT throttling activated for rt_rq %p (cpu %d)\n",
+ "sched: RT throttling activated for rt_rq %pK (cpu %d)\n",
rt_rq, cpu_of(rq_of_rt_rq(rt_rq)));
+ pos += snprintf(pos, end - pos,
+ "rt_period_timer: expires=%lld now=%llu period=%llu\n",
+ hrtimer_get_expires_ns(&rt_b->rt_period_timer),
+ ktime_get_ns(), sched_rt_period(rt_rq));
+
if (bitmap_empty(array->bitmap, MAX_RT_PRIO))
goto out;
pos += snprintf(pos, end - pos, "potential CPU hogs:\n");
+#ifdef CONFIG_SCHED_INFO
+ if (sched_info_on())
+ pos += snprintf(pos, end - pos,
+ "current %s (%d) is running for %llu nsec\n",
+ current->comm, current->pid,
+ rq_clock(rq_of_rt_rq(rt_rq)) -
+ current->sched_info.last_arrival);
+#endif
+
idx = sched_find_first_bit(array->bitmap);
while (idx < MAX_RT_PRIO) {
list_for_each_entry(rt_se, array->queue + idx, run_list) {
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 7eb1d73e..29bb99c 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1186,6 +1186,16 @@
.proc_handler = proc_dointvec_minmax,
.extra1 = &neg_one,
},
+ {
+ .procname = "hung_task_selective_monitoring",
+ .data = &sysctl_hung_task_selective_monitoring,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
+
#endif
#ifdef CONFIG_RT_MUTEXES
{
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 2aef653..a01a71f 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -94,17 +94,15 @@
};
static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
+ /* Make sure we catch unsupported clockids */
+ [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES,
+
[CLOCK_REALTIME] = HRTIMER_BASE_REALTIME,
[CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC,
[CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME,
[CLOCK_TAI] = HRTIMER_BASE_TAI,
};
-static inline int hrtimer_clockid_to_base(clockid_t clock_id)
-{
- return hrtimer_clock_to_base_table[clock_id];
-}
-
/*
* Functions and macros which are different for UP/SMP systems are kept in a
* single place
@@ -1091,6 +1089,18 @@
}
#endif
+static inline int hrtimer_clockid_to_base(clockid_t clock_id)
+{
+ if (likely(clock_id < MAX_CLOCKS)) {
+ int base = hrtimer_clock_to_base_table[clock_id];
+
+ if (likely(base != HRTIMER_MAX_CLOCK_BASES))
+ return base;
+ }
+ WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id);
+ return HRTIMER_BASE_MONOTONIC;
+}
+
static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
enum hrtimer_mode mode)
{
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 6eb61a4..0dab426 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -179,7 +179,7 @@
void get_page_bootmem(unsigned long info, struct page *page,
unsigned long type)
{
- page->lru.next = (struct list_head *) type;
+ page->freelist = (void *)type;
SetPagePrivate(page);
set_page_private(page, info);
page_ref_inc(page);
@@ -189,11 +189,12 @@
{
unsigned long type;
- type = (unsigned long) page->lru.next;
+ type = (unsigned long) page->freelist;
BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
type > MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE);
if (page_ref_dec_return(page) == 1) {
+ page->freelist = NULL;
ClearPagePrivate(page);
set_page_private(page, 0);
INIT_LIST_HEAD(&page->lru);
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 5d2f24f..622f6b6 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -255,7 +255,7 @@
{
struct kmem_cache *s;
- if (slab_nomerge || (flags & SLAB_NEVER_MERGE))
+ if (slab_nomerge)
return NULL;
if (ctor)
@@ -266,6 +266,9 @@
size = ALIGN(size, align);
flags = kmem_cache_flags(size, flags, name, NULL);
+ if (flags & SLAB_NEVER_MERGE)
+ return NULL;
+
list_for_each_entry_reverse(s, &slab_caches, list) {
if (slab_unmergeable(s))
continue;
diff --git a/mm/sparse.c b/mm/sparse.c
index 1e168bf..8c4c82e 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -662,7 +662,7 @@
>> PAGE_SHIFT;
for (i = 0; i < nr_pages; i++, page++) {
- magic = (unsigned long) page->lru.next;
+ magic = (unsigned long) page->freelist;
BUG_ON(magic == NODE_INFO);
diff --git a/net/core/dev.c b/net/core/dev.c
index 2a82be4..7aab8f6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4929,8 +4929,13 @@
while (remsd) {
struct softnet_data *next = remsd->rps_ipi_next;
- if (cpu_online(remsd->cpu))
+ if (cpu_online(remsd->cpu)) {
smp_call_function_single_async(remsd->cpu, &remsd->csd);
+ } else {
+ rps_lock(remsd);
+ remsd->backlog.state = 0;
+ rps_unlock(remsd);
+ }
remsd = next;
}
#endif
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index b2c823ff..348700b4 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -688,7 +688,7 @@
}
/* No need to do anything if the driver does all */
- if (ieee80211_hw_check(&local->hw, AP_LINK_PS))
+ if (ieee80211_hw_check(&local->hw, AP_LINK_PS) && !local->ops->set_tim)
return;
if (sta->dead)
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index f8dbacf..0d6c72d 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -411,7 +411,7 @@
struct net *net = nf_ct_exp_net(expect);
struct hlist_node *next;
unsigned int h;
- int ret = 1;
+ int ret = 0;
if (!master_help) {
ret = -ESHUTDOWN;
@@ -461,7 +461,7 @@
spin_lock_bh(&nf_conntrack_expect_lock);
ret = __nf_ct_expect_check(expect);
- if (ret <= 0)
+ if (ret < 0)
goto out;
ret = nf_ct_expect_insert(expect);
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 67c4c68..c411483 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1259,6 +1259,7 @@
struct snd_seq_port_info *info = arg;
struct snd_seq_client_port *port;
struct snd_seq_port_callback *callback;
+ int port_idx;
/* it is not allowed to create the port for an another client */
if (info->addr.client != client->number)
@@ -1269,7 +1270,9 @@
return -ENOMEM;
if (client->type == USER_CLIENT && info->kernel) {
- snd_seq_delete_port(client, port->addr.port);
+ port_idx = port->addr.port;
+ snd_seq_port_unlock(port);
+ snd_seq_delete_port(client, port_idx);
return -EINVAL;
}
if (client->type == KERNEL_CLIENT) {
@@ -1290,6 +1293,7 @@
snd_seq_set_port_info(port, info);
snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);
+ snd_seq_port_unlock(port);
return 0;
}
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index fe686ee..f04714d 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -122,7 +122,9 @@
}
-/* create a port, port number is returned (-1 on failure) */
+/* create a port, port number is returned (-1 on failure);
+ * the caller needs to unref the port via snd_seq_port_unlock() appropriately
+ */
struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
int port)
{
@@ -151,6 +153,7 @@
snd_use_lock_init(&new_port->use_lock);
port_subs_info_init(&new_port->c_src);
port_subs_info_init(&new_port->c_dest);
+ snd_use_lock_use(&new_port->use_lock);
num = port >= 0 ? port : 0;
mutex_lock(&client->ports_mutex);
@@ -165,9 +168,9 @@
list_add_tail(&new_port->list, &p->list);
client->num_ports++;
new_port->addr.port = num; /* store the port number in the port */
+ sprintf(new_port->name, "port-%d", num);
write_unlock_irqrestore(&client->ports_lock, flags);
mutex_unlock(&client->ports_mutex);
- sprintf(new_port->name, "port-%d", num);
return new_port;
}
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index c82ed3e..2007649 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -77,13 +77,17 @@
* decode input event and put to read buffer of each opened file
*/
static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
- struct snd_seq_event *ev)
+ struct snd_seq_event *ev,
+ bool atomic)
{
struct snd_virmidi *vmidi;
unsigned char msg[4];
int len;
- read_lock(&rdev->filelist_lock);
+ if (atomic)
+ read_lock(&rdev->filelist_lock);
+ else
+ down_read(&rdev->filelist_sem);
list_for_each_entry(vmidi, &rdev->filelist, list) {
if (!vmidi->trigger)
continue;
@@ -97,7 +101,10 @@
snd_rawmidi_receive(vmidi->substream, msg, len);
}
}
- read_unlock(&rdev->filelist_lock);
+ if (atomic)
+ read_unlock(&rdev->filelist_lock);
+ else
+ up_read(&rdev->filelist_sem);
return 0;
}
@@ -115,7 +122,7 @@
struct snd_virmidi_dev *rdev;
rdev = rmidi->private_data;
- return snd_virmidi_dev_receive_event(rdev, ev);
+ return snd_virmidi_dev_receive_event(rdev, ev, true);
}
#endif /* 0 */
@@ -130,7 +137,7 @@
rdev = private_data;
if (!(rdev->flags & SNDRV_VIRMIDI_USE))
return 0; /* ignored */
- return snd_virmidi_dev_receive_event(rdev, ev);
+ return snd_virmidi_dev_receive_event(rdev, ev, atomic);
}
/*
@@ -209,7 +216,6 @@
struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
struct snd_rawmidi_runtime *runtime = substream->runtime;
struct snd_virmidi *vmidi;
- unsigned long flags;
vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
if (vmidi == NULL)
@@ -223,9 +229,11 @@
vmidi->client = rdev->client;
vmidi->port = rdev->port;
runtime->private_data = vmidi;
- write_lock_irqsave(&rdev->filelist_lock, flags);
+ down_write(&rdev->filelist_sem);
+ write_lock_irq(&rdev->filelist_lock);
list_add_tail(&vmidi->list, &rdev->filelist);
- write_unlock_irqrestore(&rdev->filelist_lock, flags);
+ write_unlock_irq(&rdev->filelist_lock);
+ up_write(&rdev->filelist_sem);
vmidi->rdev = rdev;
return 0;
}
@@ -264,9 +272,11 @@
struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
struct snd_virmidi *vmidi = substream->runtime->private_data;
+ down_write(&rdev->filelist_sem);
write_lock_irq(&rdev->filelist_lock);
list_del(&vmidi->list);
write_unlock_irq(&rdev->filelist_lock);
+ up_write(&rdev->filelist_sem);
snd_midi_event_free(vmidi->parser);
substream->runtime->private_data = NULL;
kfree(vmidi);
@@ -520,6 +530,7 @@
rdev->rmidi = rmidi;
rdev->device = device;
rdev->client = -1;
+ init_rwsem(&rdev->filelist_sem);
rwlock_init(&rdev->filelist_lock);
INIT_LIST_HEAD(&rdev->filelist);
rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH;
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 775c678..bd65022 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -3685,6 +3685,7 @@
HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI", patch_i915_hsw_hdmi),
HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI", patch_i915_hsw_hdmi),
HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_i915_hsw_hdmi),
+HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_hsw_hdmi),
HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi),
HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi),
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 05cf809..d7013bd 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -13,7 +13,7 @@
config SND_SOC_MT2701_CS42448
tristate "ASoc Audio driver for MT2701 with CS42448 codec"
- depends on SND_SOC_MT2701
+ depends on SND_SOC_MT2701 && I2C
select SND_SOC_CS42XX8_I2C
select SND_SOC_BT_SCO
help
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index b871ba4..4458190 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -469,10 +469,12 @@
err = snd_usb_caiaq_send_command(cdev, EP1_CMD_GET_DEVICE_INFO, NULL, 0);
if (err)
- return err;
+ goto err_kill_urb;
- if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ))
- return -ENODEV;
+ if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) {
+ err = -ENODEV;
+ goto err_kill_urb;
+ }
usb_string(usb_dev, usb_dev->descriptor.iManufacturer,
cdev->vendor_name, CAIAQ_USB_STR_LEN);
@@ -507,6 +509,10 @@
setup_card(cdev);
return 0;
+
+ err_kill_urb:
+ usb_kill_urb(&cdev->ep1_in_urb);
+ return err;
}
static int snd_probe(struct usb_interface *intf,
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index ab3c280..58d6249 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -775,9 +775,10 @@
return 0;
error:
- if (line6->disconnect)
- line6->disconnect(line6);
- snd_card_free(card);
+ /* we can call disconnect callback here because no close-sync is
+ * needed yet at this point
+ */
+ line6_disconnect(interface);
return ret;
}
EXPORT_SYMBOL_GPL(line6_probe);
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
index 49cd4a6..5ab9e0c 100644
--- a/sound/usb/line6/podhd.c
+++ b/sound/usb/line6/podhd.c
@@ -307,6 +307,9 @@
line6->disconnect = podhd_disconnect;
+ init_timer(&pod->startup_timer);
+ INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
+
if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
/* create sysfs entries: */
err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group);
@@ -330,8 +333,6 @@
}
/* init device and delay registering */
- init_timer(&pod->startup_timer);
- INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
podhd_startup(pod);
return 0;
}
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 6c3d62f..3501ff9 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -216,7 +216,6 @@
int index, char *buf, int maxlen)
{
int len = usb_string(state->chip->dev, index, buf, maxlen - 1);
- buf[len] = 0;
return len;
}
@@ -2505,6 +2504,9 @@
static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
{
+ /* kill pending URBs */
+ snd_usb_mixer_disconnect(mixer);
+
kfree(mixer->id_elems);
if (mixer->urb) {
kfree(mixer->urb->transfer_buffer);
@@ -2938,8 +2940,13 @@
void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer)
{
- usb_kill_urb(mixer->urb);
- usb_kill_urb(mixer->rc_urb);
+ if (mixer->disconnected)
+ return;
+ if (mixer->urb)
+ usb_kill_urb(mixer->urb);
+ if (mixer->rc_urb)
+ usb_kill_urb(mixer->rc_urb);
+ mixer->disconnected = true;
}
#ifdef CONFIG_PM
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 2b4b067..545d99b 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -22,6 +22,8 @@
struct urb *rc_urb;
struct usb_ctrlrequest *rc_setup_packet;
u8 rc_buffer[6];
+
+ bool disconnected;
};
#define MAX_CHANNELS 16 /* max logical channels */