Merge "msm: vidc: Implement set property for framerate based rc" into msm-4.9
diff --git a/Documentation/devicetree/bindings/arm/msm/wil6210.txt b/Documentation/devicetree/bindings/arm/msm/wil6210.txt
index b381bdeb..c467327 100644
--- a/Documentation/devicetree/bindings/arm/msm/wil6210.txt
+++ b/Documentation/devicetree/bindings/arm/msm/wil6210.txt
@@ -10,6 +10,10 @@
 
 - compatible: "qcom,wil6210"
 - qcom,smmu-support: Boolean flag indicating whether PCIe has SMMU support
+- qcom,smmu-s1-en: Boolean flag indicating whether SMMU stage1 should be enabled
+- qcom,smmu-fast-map: Boolean flag indicating whether SMMU fast mapping should be enabled
+- qcom,smmu-coherent: Boolean flag indicating SMMU dma and page table coherency
+- qcom,smmu-mapping: specifies the base address and size of SMMU space
 - qcom,pcie-parent: phandle for the PCIe root complex to which 11ad card is connected
 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
   the below optional properties:
@@ -33,6 +37,10 @@
 	wil6210: qcom,wil6210 {
 		compatible = "qcom,wil6210";
 		qcom,smmu-support;
+		qcom,smmu-s1-en;
+		qcom,smmu-fast-map;
+		qcom,smmu-coherent;
+		qcom,smmu-mapping = <0x20000000 0xe0000000>;
 		qcom,pcie-parent = <&pcie1>;
 		qcom,wigig-en = <&tlmm 94 0>;
 		qcom,msm-bus,name = "wil6210";
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt
new file mode 100644
index 0000000..ca584e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt
@@ -0,0 +1,73 @@
+Qualcomm Technologies, Inc. SMB1355 Charger Specific Bindings
+
+SMB1355 slave charger is paired with QTI family of standalone chargers to
+enable a high current, low profile Li+ battery charging system.
+
+The device provides 28V DC withstand, wide operating input range of 3.8 to
+14.2V for standard 5V USB inputs as well as a wide variety of HVDCP Travel
+Adapters and is compatible with QTI's Quick Charge technology.
+
+=======================
+Required Node Structure
+=======================
+
+SMB1355 Charger must be described in two levels of device nodes.
+
+==================================
+First Level Node - SMB1355 Charger
+==================================
+
+Charger specific properties:
+- compatible
+  Usage:      required
+  Value type: <string>
+  Definition: "qcom,smb1355".
+
+- qcom,pmic-revid
+  Usage:      required
+  Value type: phandle
+  Definition: Should specify the phandle of SMB's revid module. This is used
+	      to identify the SMB subtype.
+
+================================================
+Second Level Nodes - SMB1355 Charger Peripherals
+================================================
+
+Peripheral specific properties:
+- reg
+  Usage:      required
+  Value type: <prop-encoded-array>
+  Definition: Address and size of the peripheral's register block.
+
+- interrupts
+  Usage:      required
+  Value type: <prop-encoded-array>
+  Definition: Peripheral interrupt specifier.
+
+- interrupt-names
+  Usage:      required
+  Value type: <stringlist>
+  Definition: Interrupt names.  This list must match up 1-to-1 with the
+	      interrupts specified in the 'interrupts' property.
+
+=======
+Example
+=======
+
+smb1355_charger: qcom,smb1355-charger {
+	compatible = "qcom,smb1355";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	qcom,chgr@1000 {
+		reg = <0x1000 0x100>;
+		interrupts = <0x10 0x1 IRQ_TYPE_EDGE_BOTH>;
+		interrupt-names = "chg-state-change";
+	};
+
+	qcom,chgr-misc@1600 {
+		reg = <0x1600 0x100>;
+		interrupts = <0x16 0x1 IRQ_TYPE_EDGE_BOTH>;
+		interrupt-names = "wdog-bark";
+	};
+};
diff --git a/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt b/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
index 04b624b..0173a3d 100644
--- a/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
+++ b/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
@@ -19,6 +19,7 @@
 Optional properties:
 - qcom,bus-mas: contains the bus master id needed to put in bus bandwidth votes
 		for inter-connect buses.
+- qcom,wakeup-byte: Byte to be injected in the tty layer during wakeup isr.
 
 Example:
 qupv3_uart11: qcom,qup_uart@0xa88000 {
@@ -34,4 +35,5 @@
 	pinctrl-1 = <&qup_1_uart_3_sleep>;
 	interrupts = <0 355 0>;
 	qcom,bus-mas = <MASTER_BLSP_2>;
+	qcom,wakeup-byte = <0xFF>;
 };
diff --git a/Makefile b/Makefile
index 2b8f550..06a55b5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 9
-SUBLEVEL = 25
+SUBLEVEL = 26
 EXTRAVERSION =
 NAME = Roaring Lionus
 
diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h
index b65930a..54b54da 100644
--- a/arch/arc/include/asm/atomic.h
+++ b/arch/arc/include/asm/atomic.h
@@ -17,10 +17,11 @@
 #include <asm/barrier.h>
 #include <asm/smp.h>
 
+#define ATOMIC_INIT(i)	{ (i) }
+
 #ifndef CONFIG_ARC_PLAT_EZNPS
 
 #define atomic_read(v)  READ_ONCE((v)->counter)
-#define ATOMIC_INIT(i)	{ (i) }
 
 #ifdef CONFIG_ARC_HAS_LLSC
 
diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h
index b5ff87e..aee1a77 100644
--- a/arch/arc/include/asm/entry-arcv2.h
+++ b/arch/arc/include/asm/entry-arcv2.h
@@ -16,6 +16,7 @@
 	;
 	; Now manually save: r12, sp, fp, gp, r25
 
+	PUSH	r30
 	PUSH	r12
 
 	; Saving pt_regs->sp correctly requires some extra work due to the way
@@ -72,6 +73,7 @@
 	POPAX	AUX_USER_SP
 1:
 	POP	r12
+	POP	r30
 
 .endm
 
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 69095da..47111d5 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -84,7 +84,7 @@
 	unsigned long fp;
 	unsigned long sp;	/* user/kernel sp depending on where we came from  */
 
-	unsigned long r12;
+	unsigned long r12, r30;
 
 	/*------- Below list auto saved by h/w -----------*/
 	unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
index 16d2474..6a3e8b4 100644
--- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
@@ -145,7 +145,6 @@
 			<0 1000>;
 
 		anoc_1_tbu: anoc_1_tbu@0x150c5000 {
-			status = "disabled";
 			compatible = "qcom,qsmmuv500-tbu";
 			reg = <0x150c5000 0x1000>,
 				<0x150c2200 0x8>;
@@ -167,7 +166,6 @@
 		};
 
 		anoc_2_tbu: anoc_2_tbu@0x150c9000 {
-			status = "disabled";
 			compatible = "qcom,qsmmuv500-tbu";
 			reg = <0x150c9000 0x1000>,
 				<0x150c2208 0x8>;
@@ -189,7 +187,6 @@
 		};
 
 		mnoc_hf_0_tbu: mnoc_hf_0_tbu@0x150cd000 {
-			status = "disabled";
 			compatible = "qcom,qsmmuv500-tbu";
 			reg = <0x150cd000 0x1000>,
 				<0x150c2210 0x8>;
@@ -211,7 +208,6 @@
 		};
 
 		mnoc_hf_1_tbu: mnoc_hf_1_tbu@0x150d1000 {
-			status = "disabled";
 			compatible = "qcom,qsmmuv500-tbu";
 			reg = <0x150d1000 0x1000>,
 				<0x150c2218 0x8>;
@@ -233,7 +229,6 @@
 		};
 
 		mnoc_sf_0_tbu: mnoc_sf_0_tbu@0x150d5000 {
-			status = "disabled";
 			compatible = "qcom,qsmmuv500-tbu";
 			reg = <0x150d5000 0x1000>,
 				<0x150c2220 0x8>;
@@ -255,7 +250,6 @@
 		};
 
 		compute_dsp_tbu: compute_dsp_tbu@0x150d9000 {
-			status = "disabled";
 			compatible = "qcom,qsmmuv500-tbu";
 			reg = <0x150d9000 0x1000>,
 				<0x150c2228 0x8>;
@@ -276,7 +270,6 @@
 		};
 
 		adsp_tbu: adsp_tbu@0x150dd000 {
-			status = "disabled";
 			compatible = "qcom,qsmmuv500-tbu";
 			reg = <0x150dd000 0x1000>,
 				<0x150c2230 0x8>;
@@ -298,7 +291,6 @@
 		};
 
 		anoc_1_pcie_tbu: anoc_1_pcie_tbu@0x150e1000 {
-			status = "disabled";
 			compatible = "qcom,qsmmuv500-tbu";
 			reg = <0x150e1000 0x1000>,
 				<0x150c2238 0x8>;
@@ -336,9 +328,9 @@
 	apps_iommu_test_device {
 		compatible = "iommu-debug-test";
 		/*
-		 * This SID belongs to PCIE. We can't use a fake SID for
+		 * This SID belongs to QUP1-GSI. We can't use a fake SID for
 		 * the apps_smmu device.
 		 */
-		iommus = <&apps_smmu 0x1c03 0>;
+		iommus = <&apps_smmu 0x16 0>;
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi
index b119305..b9a6c79 100644
--- a/arch/arm64/boot/dts/qcom/pm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi
@@ -67,6 +67,8 @@
 			reg = <0x2400 0x100>;
 			interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>;
 			label = "pm8998_tz";
+			qcom,channel-num = <6>;
+			qcom,temp_alarm-vadc = <&pm8998_vadc>;
 			#thermal-sensor-cells = <0>;
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index 6f40fae..af28003 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -206,6 +206,7 @@
 		spi0 = &qupv3_se8_spi;
 		i2c0 = &qupv3_se10_i2c;
 		i2c1 = &qupv3_se3_i2c;
+		hsuart0 = &qupv3_se6_4uart;
 	};
 };
 
@@ -249,6 +250,10 @@
 	status = "ok";
 };
 
+&qupv3_se6_4uart {
+	status = "ok";
+};
+
 &usb1 {
 	status = "okay";
 	extcon = <&extcon_usb1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
index 91946d7..d1712ad 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
@@ -483,6 +483,16 @@
 			};
 
 			port@1 {
+				reg = <0>;
+				funnel_in2_in_modem_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+					  <&modem_etm0_out_funnel_in2>;
+				};
+
+			};
+
+			port@2 {
 				reg = <1>;
 				funnel_in2_in_replicator_swao: endpoint {
 					slave-mode;
@@ -492,7 +502,7 @@
 
 			};
 
-			port@2 {
+			port@3 {
 				reg = <2>;
 				funnel_in2_in_funnel_modem: endpoint {
 					slave-mode;
@@ -502,7 +512,7 @@
 
 			};
 
-			port@3 {
+			port@4 {
 				reg = <5>;
 				funnel_in2_in_funnel_apss_merg: endpoint {
 					slave-mode;
@@ -1746,6 +1756,20 @@
 		};
 	};
 
+	modem_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+
+		coresight-name = "coresight-modem-etm0";
+		qcom,inst-id = <2>;
+
+		port {
+			modem_etm0_out_funnel_in2: endpoint {
+				remote-endpoint =
+					<&funnel_in2_in_modem_etm0>;
+			};
+		};
+	};
+
 	funnel_apss_merg: funnel@7810000 {
 		compatible = "arm,primecell";
 		arm,primecell-periphid = <0x0003b908>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
index 0ada391..77edb85 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
@@ -12,6 +12,12 @@
 
 &soc {
 
+	pil_gpu: qcom,kgsl-hyp {
+		compatible = "qcom,pil-tz-generic";
+		qcom,pas-id = <13>;
+		qcom,firmware-name = "a630_zap";
+	};
+
 	msm_bus: qcom,kgsl-busmon{
 		label = "kgsl-busmon";
 		compatible = "qcom,kgsl-busmon";
@@ -165,19 +171,19 @@
 
 			qcom,gpu-pwrlevel@0 {
 				reg = <0>;
-				qcom,gpu-freq = <548000000>;
-				qcom,bus-freq = <12>;
-				qcom,bus-min = <11>;
-				qcom,bus-max = <12>;
+				qcom,gpu-freq = <280000000>;
+				qcom,bus-freq = <4>;
+				qcom,bus-min = <3>;
+				qcom,bus-max = <5>;
 			};
 
 
 			qcom,gpu-pwrlevel@1 {
 				reg = <1>;
-				qcom,gpu-freq = <425000000>;
-				qcom,bus-freq = <7>;
-				qcom,bus-min = <6>;
-				qcom,bus-max = <8>;
+				qcom,gpu-freq = <280000000>;
+				qcom,bus-freq = <4>;
+				qcom,bus-min = <3>;
+				qcom,bus-max = <5>;
 			};
 
 			qcom,gpu-pwrlevel@2 {
@@ -190,10 +196,10 @@
 
 			qcom,gpu-pwrlevel@3 {
 				reg = <3>;
-				qcom,gpu-freq = <27000000>;
-				qcom,bus-freq = <0>;
-				qcom,bus-min = <0>;
-				qcom,bus-max = <0>;
+				qcom,gpu-freq = <280000000>;
+				qcom,bus-freq = <4>;
+				qcom,bus-min = <3>;
+				qcom,bus-max = <5>;
 			};
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index 803843c..d316d63 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -12,6 +12,7 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include "sdm845-camera-sensor-mtp.dtsi"
+#include "smb1355.dtsi"
 
 / {
 	bluetooth: bt_wcn3990 {
@@ -203,12 +204,17 @@
 	qcom,battery-data = <&mtp_batterydata>;
 };
 
+&smb1355_charger {
+	status = "ok";
+};
+
 / {
 aliases {
 		serial0 = &qupv3_se9_2uart;
 		spi0 = &qupv3_se8_spi;
 		i2c0 = &qupv3_se10_i2c;
 		i2c1 = &qupv3_se3_i2c;
+		hsuart0 = &qupv3_se6_4uart;
 	};
 };
 
@@ -228,6 +234,10 @@
 	status = "ok";
 };
 
+&qupv3_se6_4uart {
+	status = "ok";
+};
+
 &usb1 {
 	status = "okay";
 	extcon = <&extcon_usb1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pcie.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pcie.dtsi
new file mode 100644
index 0000000..da5d6fa
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-pcie.dtsi
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+
+&soc {
+	pcie0: qcom,pcie@0x1c00000 {
+		compatible = "qcom,pci-msm";
+		cell-index = <0>;
+
+		reg = <0x1c00000 0x2000>,
+		      <0x1c06000 0x1000>,
+		      <0x60000000 0xf1d>,
+		      <0x60000f20 0xa8>,
+		      <0x60100000 0x100000>,
+		      <0x60200000 0x100000>,
+		      <0x60300000 0xd00000>;
+
+		reg-names = "parf", "phy", "dm_core", "elbi",
+				"conf", "io", "bars";
+
+		#address-cells = <3>;
+		#size-cells = <2>;
+		ranges = <0x01000000 0x0 0x60200000 0x60200000 0x0 0x100000>,
+			<0x02000000 0x0 0x60300000 0x60300000 0x0 0xd00000>;
+		interrupt-parent = <&pcie0>;
+		interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+				20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
+				36 37>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0xffffffff>;
+		interrupt-map = <0 0 0 0 &intc 0 141 0
+				0 0 0 1 &intc 0 149 0
+				0 0 0 2 &intc 0 150 0
+				0 0 0 3 &intc 0 151 0
+				0 0 0 4 &intc 0 152 0
+				0 0 0 5 &intc 0 140 0
+				0 0 0 6 &intc 0 672 0
+				0 0 0 7 &intc 0 673 0
+				0 0 0 8 &intc 0 674 0
+				0 0 0 9 &intc 0 675 0
+				0 0 0 10 &intc 0 676 0
+				0 0 0 11 &intc 0 677 0
+				0 0 0 12 &intc 0 678 0
+				0 0 0 13 &intc 0 679 0
+				0 0 0 14 &intc 0 680 0
+				0 0 0 15 &intc 0 681 0
+				0 0 0 16 &intc 0 682 0
+				0 0 0 17 &intc 0 683 0
+				0 0 0 18 &intc 0 684 0
+				0 0 0 19 &intc 0 685 0
+				0 0 0 20 &intc 0 686 0
+				0 0 0 21 &intc 0 687 0
+				0 0 0 22 &intc 0 688 0
+				0 0 0 23 &intc 0 689 0
+				0 0 0 24 &intc 0 690 0
+				0 0 0 25 &intc 0 691 0
+				0 0 0 26 &intc 0 692 0
+				0 0 0 27 &intc 0 693 0
+				0 0 0 28 &intc 0 694 0
+				0 0 0 29 &intc 0 695 0
+				0 0 0 30 &intc 0 696 0
+				0 0 0 31 &intc 0 697 0
+				0 0 0 32 &intc 0 698 0
+				0 0 0 33 &intc 0 699 0
+				0 0 0 34 &intc 0 700 0
+				0 0 0 35 &intc 0 701 0
+				0 0 0 36 &intc 0 702 0
+				0 0 0 37 &intc 0 703 0>;
+
+		interrupt-names = "int_msi", "int_a", "int_b", "int_c",
+				"int_d", "int_global_int",
+				"msi_0", "msi_1", "msi_2", "msi_3",
+				"msi_4", "msi_5", "msi_6", "msi_7",
+				"msi_8", "msi_9", "msi_10", "msi_11",
+				"msi_12", "msi_13", "msi_14", "msi_15",
+				"msi_16", "msi_17", "msi_18", "msi_19",
+				"msi_20", "msi_21", "msi_22", "msi_23",
+				"msi_24", "msi_25", "msi_26", "msi_27",
+				"msi_28", "msi_29", "msi_30", "msi_31";
+
+		qcom,phy-sequence = <0x804 0x01 0x0
+					0x034 0x14 0x0
+					0x138 0x30 0x0
+					0x048 0x07 0x0
+					0x15c 0x06 0x0
+					0x090 0x01 0x0
+					0x088 0x20 0x0
+					0x0f0 0x00 0x0
+					0x0f8 0x01 0x0
+					0x0f4 0xc9 0x0
+					0x11c 0xff 0x0
+					0x120 0x3f 0x0
+					0x164 0x01 0x0
+					0x154 0x00 0x0
+					0x148 0x0a 0x0
+					0x05c 0x19 0x0
+					0x038 0x90 0x0
+					0x0b0 0x82 0x0
+					0x0c0 0x02 0x0
+					0x0bc 0xea 0x0
+					0x0b8 0xab 0x0
+					0x0a0 0x00 0x0
+					0x09c 0x0d 0x0
+					0x098 0x04 0x0
+					0x13c 0x00 0x0
+					0x060 0x06 0x0
+					0x068 0x16 0x0
+					0x070 0x36 0x0
+					0x184 0x01 0x0
+					0x15c 0x16 0x0
+					0x138 0x33 0x0
+					0x03c 0x02 0x0
+					0x040 0x07 0x0
+					0x080 0x04 0x0
+					0x0dc 0x00 0x0
+					0x0d8 0x3f 0x0
+					0x00c 0x09 0x0
+					0x010 0x01 0x0
+					0x01c 0x40 0x0
+					0x020 0x01 0x0
+					0x014 0x02 0x0
+					0x018 0x00 0x0
+					0x024 0x7e 0x0
+					0x028 0x15 0x0
+					0x244 0x02 0x0
+					0x2a4 0x12 0x0
+					0x260 0x10 0x0
+					0x28c 0x06 0x0
+					0x504 0x03 0x0
+					0x500 0x1c 0x0
+					0x50c 0x14 0x0
+					0x4d4 0x0e 0x0
+					0x4d8 0x04 0x0
+					0x4dc 0x1a 0x0
+					0x434 0x4b 0x0
+					0x414 0x04 0x0
+					0x40c 0x04 0x0
+					0x4f8 0x71 0x0
+					0x564 0x59 0x0
+					0x568 0x59 0x0
+					0x4fc 0x80 0x0
+					0x51c 0x40 0x0
+					0x444 0x71 0x0
+					0x43c 0x40 0x0
+					0x854 0x04 0x0
+					0x62c 0x52 0x0
+					0x654 0x50 0x0
+					0x65c 0x1a 0x0
+					0x660 0x06 0x0
+					0x8c8 0x83 0x0
+					0x8cc 0x09 0x0
+					0x8d0 0xa2 0x0
+					0x8d4 0x40 0x0
+					0x8c4 0x02 0x0
+					0x9ac 0x00 0x0
+					0x8a0 0x01 0x0
+					0x9e0 0x00 0x0
+					0x9dc 0x20 0x0
+					0x9a8 0x00 0x0
+					0x8a4 0x01 0x0
+					0x8a8 0x73 0x0
+					0x9d8 0xaa 0x0
+					0x9b0 0x03 0x0
+					0xa0c 0x0d 0x0
+					0x86c 0x00 0x0
+					0x644 0x00 0x0
+					0x804 0x03 0x0
+					0x800 0x00 0x0
+					0x808 0x03 0x0>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pcie0_clkreq_default
+			&pcie0_perst_default
+			&pcie0_wake_default>;
+
+		perst-gpio = <&tlmm 35 0>;
+		wake-gpio = <&tlmm 37 0>;
+
+		gdsc-vdd-supply = <&pcie_0_gdsc>;
+		vreg-1.8-supply = <&pm8998_l26>;
+		vreg-0.9-supply = <&pm8998_l1>;
+		vreg-cx-supply = <&pm8998_s9_level>;
+
+		qcom,vreg-1.8-voltage-level = <1200000 1200000 24000>;
+		qcom,vreg-0.9-voltage-level = <880000 880000 24000>;
+		qcom,vreg-cx-voltage-level = <RPMH_REGULATOR_LEVEL_MAX
+						RPMH_REGULATOR_LEVEL_SVS 0>;
+
+		qcom,l1-supported;
+		qcom,l1ss-supported;
+		qcom,aux-clk-sync;
+
+		qcom,ep-latency = <10>;
+
+		qcom,boot-option = <0x1>;
+
+		linux,pci-domain = <0>;
+
+		qcom,msi-gicm-addr = <0x17a00040>;
+		qcom,msi-gicm-base = <0x2c0>;
+
+		qcom,pcie-phy-ver = <0x30>;
+		qcom,use-19p2mhz-aux-clk;
+
+		qcom,smmu-sid-base = <0x1c10>;
+
+		iommu-map = <0x100 &apps_smmu 0x1c11 0x1>,
+			<0x200 &apps_smmu 0x1c12 0x1>,
+			<0x300 &apps_smmu 0x1c13 0x1>,
+			<0x400 &apps_smmu 0x1c14 0x1>,
+			<0x500 &apps_smmu 0x1c15 0x1>,
+			<0x600 &apps_smmu 0x1c16 0x1>,
+			<0x700 &apps_smmu 0x1c17 0x1>,
+			<0x800 &apps_smmu 0x1c18 0x1>,
+			<0x900 &apps_smmu 0x1c19 0x1>,
+			<0xa00 &apps_smmu 0x1c1a 0x1>,
+			<0xb00 &apps_smmu 0x1c1b 0x1>,
+			<0xc00 &apps_smmu 0x1c1c 0x1>,
+			<0xd00 &apps_smmu 0x1c1d 0x1>,
+			<0xe00 &apps_smmu 0x1c1e 0x1>,
+			<0xf00 &apps_smmu 0x1c1f 0x1>;
+
+		qcom,msm-bus,name = "pcie0";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<45 512 0 0>,
+				<45 512 500 800>;
+
+		clocks = <&clock_gcc GCC_PCIE_0_PIPE_CLK>,
+			<&clock_rpmh RPMH_CXO_CLK>,
+			<&clock_gcc GCC_PCIE_0_AUX_CLK>,
+			<&clock_gcc GCC_PCIE_0_CFG_AHB_CLK>,
+			<&clock_gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+			<&clock_gcc GCC_PCIE_0_SLV_AXI_CLK>,
+			<&clock_gcc GCC_PCIE_0_CLKREF_CLK>,
+			<&clock_gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>,
+			<&clock_gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>,
+			<&clock_gcc GCC_PCIE_PHY_REFGEN_CLK>,
+			<&clock_gcc GCC_PCIE_PHY_AUX_CLK>;
+
+		clock-names = "pcie_0_pipe_clk", "pcie_0_ref_clk_src",
+				"pcie_0_aux_clk", "pcie_0_cfg_ahb_clk",
+				"pcie_0_mstr_axi_clk", "pcie_0_slv_axi_clk",
+				"pcie_0_ldo", "pcie_0_slv_q2a_axi_clk",
+				"pcie_tbu_clk", "pcie_phy_refgen_clk",
+				"pcie_phy_aux_clk";
+
+		max-clock-frequency-hz = <0>, <0>, <19200000>, <0>, <0>,
+					<0>, <0>, <0>, <0>, <100000000>, <0>;
+
+		resets = <&clock_gcc GCC_PCIE_0_BCR>,
+			<&clock_gcc GCC_PCIE_0_PHY_BCR>;
+
+		reset-names = "pcie_0_core_reset",
+				"pcie_0_phy_reset";
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
index bc535d1..3ab0c70 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
@@ -160,6 +160,47 @@
 			};
 		};
 
+		pcie0 {
+			pcie0_clkreq_default: pcie0_clkreq_default {
+				mux {
+					pins = "gpio36";
+					function = "pci_e0";
+				};
+
+				config {
+					pins = "gpio36";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+
+			pcie0_perst_default: pcie0_perst_default {
+				mux {
+					pins = "gpio35";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio35";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+
+			pcie0_wake_default: pcie0_wake_default {
+				mux {
+					pins = "gpio37";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio37";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
 		cdc_reset_ctrl {
 			cdc_reset_sleep: cdc_reset_sleep {
 				mux {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
index a4dc4753..e21ed36 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
@@ -10,6 +10,8 @@
  * GNU General Public License for more details.
  */
 
+#include "smb1355.dtsi"
+
 /{
 	qrd_batterydata: qcom,battery-data {
 		qcom,batt-id-range-pct = <15>;
@@ -22,6 +24,10 @@
 	qcom,battery-data = <&qrd_batterydata>;
 };
 
+&smb1355_charger {
+	status = "ok";
+};
+
 &mdss_mdp {
 	#cooling-cells = <2>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
index dd0d08e..e5d1a74 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
@@ -30,9 +30,11 @@
 		pinctrl-names = "default", "sleep";
 		pinctrl-0 = <&qupv3_se6_4uart_active>;
 		pinctrl-1 = <&qupv3_se6_4uart_sleep>;
-		interrupts = <GIC_SPI 607 0>;
+		interrupts-extended = <&intc GIC_SPI 607 0>,
+				<&tlmm 48 0>;
 		status = "disabled";
 		qcom,bus-mas = <MSM_BUS_MASTER_BLSP_1>;
+		qcom,wakeup-byte = <0xFD>;
 	};
 
 	qupv3_se7_4uart: qcom,qup_uart@0x89c000 {
@@ -46,9 +48,11 @@
 		pinctrl-names = "default", "sleep";
 		pinctrl-0 = <&qupv3_se7_4uart_active>;
 		pinctrl-1 = <&qupv3_se7_4uart_sleep>;
-		interrupts = <GIC_SPI 608 0>;
+		interrupts-extended = <&intc GIC_SPI 608 0>,
+				<&tlmm 96 0>;
 		status = "disabled";
 		qcom,bus-mas = <MSM_BUS_MASTER_BLSP_1>;
+		qcom,wakeup-byte = <0xFD>;
 	};
 
 	/* I2C */
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index 7812a48..af63d22 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -209,7 +209,6 @@
 	};
 
 	mdss_rotator: qcom,mdss_rotator@ae00000 {
-		status = "disabled";
 		compatible = "qcom,sde_rotator";
 		reg = <0x0ae00000 0xac000>,
 		      <0x0aeb8000 0x3000>;
@@ -260,14 +259,11 @@
 		smmu_rot_unsec: qcom,smmu_rot_unsec_cb {
 			compatible = "qcom,smmu_sde_rot_unsec";
 			iommus = <&apps_smmu 0x1090 0x0>;
-			gdsc-mdss-supply = <&hlos1_vote_mmnoc_mmu_tbu_sf_gdsc>;
 		};
 
 		smmu_rot_sec: qcom,smmu_rot_sec_cb {
-			status = "disabled";
 			compatible = "qcom,smmu_sde_rot_sec";
 			iommus = <&apps_smmu 0x1091 0x0>;
-			gdsc-mdss-supply = <&hlos1_vote_mmnoc_mmu_tbu_sf_gdsc>;
 		};
 	};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 5660841..72c2efa 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -34,6 +34,7 @@
 	aliases {
 		ufshc1 = &ufshc_mem; /* Embedded UFS slot */
 		ufshc2 = &ufshc_card; /* Removable UFS slot */
+		pci-domain0 = &pcie0;
 		sdhc2 = &sdhc_2; /* SDC2 SD card slot */
 	};
 
@@ -1061,7 +1062,7 @@
 		status = "disabled";
 	};
 
-	ufshc_mem: ufshc_mem@1d84000 {
+	ufshc_mem: ufshc@1d84000 {
 		compatible = "qcom,ufshc";
 		reg = <0x1d84000 0x2500>;
 		interrupts = <0 265 0>;
@@ -1446,6 +1447,7 @@
 	};
 
 	slim_qca: slim@17240000 {
+		status = "ok";
 		cell-index = <3>;
 		compatible = "qcom,slim-ngd";
 		reg = <0x17240000 0x2c000>,
@@ -1453,6 +1455,14 @@
 		reg-names = "slimbus_physical", "slimbus_bam_physical";
 		interrupts = <0 291 0>, <0 292 0>;
 		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+
+		/* Slimbus Slave DT for WCN3990 */
+		btfmslim_codec: wcn3990 {
+			compatible = "qcom,btfmslim_slave";
+			elemental-addr = [00 01 20 02 17 02];
+			qcom,btfm-slim-ifd = "btfmslim_slave_ifd";
+			qcom,btfm-slim-ifd-elemental-addr = [00 00 20 02 17 02];
+		};
 	};
 
 	eud: qcom,msm-eud@88e0000 {
@@ -3639,6 +3649,7 @@
 #include "sdm845-vidc.dtsi"
 #include "sdm845-pm.dtsi"
 #include "sdm845-pinctrl.dtsi"
+#include "sdm845-pcie.dtsi"
 #include "sdm845-audio.dtsi"
 #include "sdm845-gpu.dtsi"
 #include "sdm845-usb.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/smb1355.dtsi b/arch/arm64/boot/dts/qcom/smb1355.dtsi
new file mode 100644
index 0000000..33c5e97
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/smb1355.dtsi
@@ -0,0 +1,55 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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/interrupt-controller/irq.h>
+
+&qupv3_se10_i2c {
+	smb1355: qcom,smb1355@8 {
+		compatible = "qcom,i2c-pmic";
+		reg = <0x8>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-parent = <&spmi_bus>;
+		interrupts = <0x0 0xd1 0x0 IRQ_TYPE_LEVEL_LOW>;
+		interrupt_names = "smb1355";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		qcom,periph-map = <0x10 0x12 0x13 0x16>;
+
+		smb1355_revid: qcom,revid@100 {
+			compatible = "qcom,qpnp-revid";
+			reg = <0x100 0x100>;
+		};
+
+		smb1355_charger: qcom,smb1355-charger@1000 {
+			compatible = "qcom,smb1355";
+			qcom,pmic-revid = <&smb1355_revid>;
+			reg = <0x1000 0x700>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			interrupt-parent = <&smb1355>;
+			status = "disabled";
+
+			qcom,chgr@1000 {
+				reg = <0x1000 0x100>;
+				interrupts = <0x10 0x1 IRQ_TYPE_EDGE_RISING>;
+				interrupt-names = "chg-state-change";
+			};
+
+			qcom,chgr-misc@1600 {
+				reg = <0x1600 0x100>;
+				interrupts = <0x16 0x1 IRQ_TYPE_EDGE_RISING>;
+				interrupt-names = "wdog-bark";
+			};
+		};
+	};
+};
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 7f00787..531d236 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -49,6 +49,7 @@
 CONFIG_ARCH_SDM845=y
 CONFIG_ARCH_SDM830=y
 CONFIG_PCI=y
+CONFIG_PCI_MSM=y
 CONFIG_SCHED_MC=y
 CONFIG_NR_CPUS=8
 CONFIG_PREEMPT=y
@@ -238,6 +239,7 @@
 CONFIG_SCSI_UFSHCD=y
 CONFIG_SCSI_UFSHCD_PLATFORM=y
 CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
@@ -298,8 +300,8 @@
 CONFIG_POWER_RESET_XGENE=y
 CONFIG_POWER_RESET_SYSCON=y
 CONFIG_QPNP_FG_GEN3=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
 CONFIG_QPNP_SMB2=y
-CONFIG_SMB138X_CHARGER=y
 CONFIG_QPNP_QNOVO=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_THERMAL=y
@@ -477,6 +479,7 @@
 CONFIG_ICNSS=y
 CONFIG_QCOM_COMMAND_DB=y
 CONFIG_MSM_ADSP_LOADER=y
+CONFIG_MSM_CDSP_LOADER=y
 CONFIG_MSM_AVTIMER=y
 CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_PM=y
@@ -541,7 +544,10 @@
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_ANSI_CPRNG=y
-CONFIG_CRYPTO_DEV_QCE=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
 CONFIG_ARM64_CRYPTO=y
 CONFIG_CRYPTO_SHA1_ARM64_CE=y
 CONFIG_CRYPTO_SHA2_ARM64_CE=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 4fdbffa..cbcf515 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -54,12 +54,14 @@
 CONFIG_ARCH_SDM845=y
 CONFIG_ARCH_SDM830=y
 CONFIG_PCI=y
+CONFIG_PCI_MSM=y
 CONFIG_SCHED_MC=y
 CONFIG_NR_CPUS=8
 CONFIG_PREEMPT=y
 CONFIG_HZ_100=y
 CONFIG_CLEANCACHE=y
 CONFIG_CMA=y
+CONFIG_CMA_DEBUGFS=y
 CONFIG_ZSMALLOC=y
 CONFIG_BALANCE_ANON_FILE_RECLAIM=y
 CONFIG_SECCOMP=y
@@ -248,6 +250,7 @@
 CONFIG_SCSI_UFSHCD=y
 CONFIG_SCSI_UFSHCD_PLATFORM=y
 CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
@@ -306,8 +309,8 @@
 CONFIG_POWER_RESET_XGENE=y
 CONFIG_POWER_RESET_SYSCON=y
 CONFIG_QPNP_FG_GEN3=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
 CONFIG_QPNP_SMB2=y
-CONFIG_SMB138X_CHARGER=y
 CONFIG_QPNP_QNOVO=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_THERMAL=y
@@ -496,6 +499,7 @@
 CONFIG_ICNSS_DEBUG=y
 CONFIG_QCOM_COMMAND_DB=y
 CONFIG_MSM_ADSP_LOADER=y
+CONFIG_MSM_CDSP_LOADER=y
 CONFIG_MSM_AVTIMER=y
 CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_PM=y
@@ -610,7 +614,10 @@
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_ANSI_CPRNG=y
-CONFIG_CRYPTO_DEV_QCE=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
 CONFIG_ARM64_CRYPTO=y
 CONFIG_CRYPTO_SHA1_ARM64_CE=y
 CONFIG_CRYPTO_SHA2_ARM64_CE=y
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 804d2a2..dd6a18b 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -80,7 +80,7 @@
 		}
 
 		/* Sorted insert of 75th percentile into buf2 */
-		for (k = 0; k < i; ++k) {
+		for (k = 0; k < i && k < ARRAY_SIZE(buf2); ++k) {
 			if (buf1[ARRAY_SIZE(buf1) - 1] < buf2[k]) {
 				l = min_t(unsigned int,
 					  i, ARRAY_SIZE(buf2) - 1);
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index 6430bff..5c429d7 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -257,7 +257,7 @@
 	else if ((prog_req.fr1 && prog_req.frdefault) ||
 		 (prog_req.single && !prog_req.frdefault))
 		/* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */
-		state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
+		state->overall_fp_mode = ((raw_current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
 					  cpu_has_mips_r2_r6) ?
 					  FP_FR1 : FP_FR0;
 	else if (prog_req.fr1)
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index de63d36..732d617 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -244,9 +244,6 @@
 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
 {
 	int reg;
-	struct thread_info *ti = task_thread_info(p);
-	unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32;
-	struct pt_regs *regs = (struct pt_regs *)ksp - 1;
 #if (KGDB_GDB_REG_SIZE == 32)
 	u32 *ptr = (u32 *)gdb_regs;
 #else
@@ -254,25 +251,46 @@
 #endif
 
 	for (reg = 0; reg < 16; reg++)
-		*(ptr++) = regs->regs[reg];
+		*(ptr++) = 0;
 
 	/* S0 - S7 */
-	for (reg = 16; reg < 24; reg++)
-		*(ptr++) = regs->regs[reg];
+	*(ptr++) = p->thread.reg16;
+	*(ptr++) = p->thread.reg17;
+	*(ptr++) = p->thread.reg18;
+	*(ptr++) = p->thread.reg19;
+	*(ptr++) = p->thread.reg20;
+	*(ptr++) = p->thread.reg21;
+	*(ptr++) = p->thread.reg22;
+	*(ptr++) = p->thread.reg23;
 
 	for (reg = 24; reg < 28; reg++)
 		*(ptr++) = 0;
 
 	/* GP, SP, FP, RA */
-	for (reg = 28; reg < 32; reg++)
-		*(ptr++) = regs->regs[reg];
+	*(ptr++) = (long)p;
+	*(ptr++) = p->thread.reg29;
+	*(ptr++) = p->thread.reg30;
+	*(ptr++) = p->thread.reg31;
 
-	*(ptr++) = regs->cp0_status;
-	*(ptr++) = regs->lo;
-	*(ptr++) = regs->hi;
-	*(ptr++) = regs->cp0_badvaddr;
-	*(ptr++) = regs->cp0_cause;
-	*(ptr++) = regs->cp0_epc;
+	*(ptr++) = p->thread.cp0_status;
+
+	/* lo, hi */
+	*(ptr++) = 0;
+	*(ptr++) = 0;
+
+	/*
+	 * BadVAddr, Cause
+	 * Ideally these would come from the last exception frame up the stack
+	 * but that requires unwinding, otherwise we can't know much for sure.
+	 */
+	*(ptr++) = 0;
+	*(ptr++) = 0;
+
+	/*
+	 * PC
+	 * use return address (RA), i.e. the moment after return from resume()
+	 */
+	*(ptr++) = p->thread.reg31;
 }
 
 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 1fb317f..b6802b9 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -673,6 +673,14 @@
 	return pte_pfn(pte);
 }
 
+#define __HAVE_ARCH_PMD_WRITE
+static inline unsigned long pmd_write(pmd_t pmd)
+{
+	pte_t pte = __pte(pmd_val(pmd));
+
+	return pte_write(pte);
+}
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 static inline unsigned long pmd_dirty(pmd_t pmd)
 {
@@ -688,13 +696,6 @@
 	return pte_young(pte);
 }
 
-static inline unsigned long pmd_write(pmd_t pmd)
-{
-	pte_t pte = __pte(pmd_val(pmd));
-
-	return pte_write(pte);
-}
-
 static inline unsigned long pmd_trans_huge(pmd_t pmd)
 {
 	pte_t pte = __pte(pmd_val(pmd));
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 37aa537..bd7e2aa 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1495,7 +1495,7 @@
 	if ((long)addr < 0L) {
 		unsigned long pa = __pa(addr);
 
-		if ((addr >> max_phys_bits) != 0UL)
+		if ((pa >> max_phys_bits) != 0UL)
 			return false;
 
 		return pfn_valid(pa >> PAGE_SHIFT);
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 8639bb2..6bf09f5 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -983,6 +983,18 @@
 	unsigned long return_hooker = (unsigned long)
 				&return_to_handler;
 
+	/*
+	 * When resuming from suspend-to-ram, this function can be indirectly
+	 * called from early CPU startup code while the CPU is in real mode,
+	 * which would fail miserably.  Make sure the stack pointer is a
+	 * virtual address.
+	 *
+	 * This check isn't as accurate as virt_addr_valid(), but it should be
+	 * good enough for this purpose, and it's fast.
+	 */
+	if (unlikely((long)__builtin_frame_address(0) >= 0))
+		return;
+
 	if (unlikely(ftrace_graph_is_dead()))
 		return;
 
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index 8487f46..3c3f335 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -105,9 +105,13 @@
 
 static void rd_write(struct msm_rd_state *rd, const void *buf, int sz)
 {
-	struct circ_buf *fifo = &rd->fifo;
+	struct circ_buf *fifo;
 	const char *ptr = buf;
 
+	if (!rd || !buf)
+		return;
+
+	fifo = &rd->fifo;
 	while (sz > 0) {
 		char *fptr = &fifo->buf[fifo->head];
 		int n;
@@ -136,11 +140,18 @@
 static ssize_t rd_read(struct file *file, char __user *buf,
 		size_t sz, loff_t *ppos)
 {
-	struct msm_rd_state *rd = file->private_data;
-	struct circ_buf *fifo = &rd->fifo;
-	const char *fptr = &fifo->buf[fifo->tail];
+	struct msm_rd_state *rd;
+	struct circ_buf *fifo;
+	const char *fptr;
 	int n = 0, ret = 0;
 
+	if (!file || !file->private_data || !buf || !ppos)
+		return -EINVAL;
+
+	rd = file->private_data;
+	fifo = &rd->fifo;
+	fptr = &fifo->buf[fifo->tail];
+
 	mutex_lock(&rd->read_lock);
 
 	ret = wait_event_interruptible(rd->fifo_event,
@@ -168,19 +179,34 @@
 
 static int rd_open(struct inode *inode, struct file *file)
 {
-	struct msm_rd_state *rd = inode->i_private;
-	struct drm_device *dev = rd->dev;
-	struct msm_drm_private *priv = dev->dev_private;
-	struct msm_gpu *gpu = priv->gpu;
+	struct msm_rd_state *rd;
+	struct drm_device *dev;
+	struct msm_drm_private *priv;
+	struct msm_gpu *gpu;
 	uint64_t val;
 	uint32_t gpu_id;
 	int ret = 0;
 
+	if (!file || !inode || !inode->i_private)
+		return -EINVAL;
+
+	rd = inode->i_private;
+	dev = rd->dev;
+
+	if (!dev || !dev->dev_private)
+		return -EINVAL;
+
+	priv = dev->dev_private;
+	gpu = priv->gpu;
+
 	mutex_lock(&dev->struct_mutex);
 
 	if (rd->open || !gpu) {
 		ret = -EBUSY;
 		goto out;
+	} else if (!gpu->funcs || !gpu->funcs->get_param) {
+		ret = -EINVAL;
+		goto out;
 	}
 
 	file->private_data = rd;
@@ -201,7 +227,12 @@
 
 static int rd_release(struct inode *inode, struct file *file)
 {
-	struct msm_rd_state *rd = inode->i_private;
+	struct msm_rd_state *rd;
+
+	if (!inode || !inode->i_private)
+		return -EINVAL;
+
+	rd = inode->i_private;
 	rd->open = false;
 	return 0;
 }
@@ -217,9 +248,14 @@
 
 int msm_rd_debugfs_init(struct drm_minor *minor)
 {
-	struct msm_drm_private *priv = minor->dev->dev_private;
+	struct msm_drm_private *priv;
 	struct msm_rd_state *rd;
 
+	if (!minor || !minor->dev || !minor->dev->dev_private)
+		return -EINVAL;
+
+	priv = minor->dev->dev_private;
+
 	/* only create on first minor: */
 	if (priv->rd)
 		return 0;
@@ -265,8 +301,14 @@
 
 void msm_rd_debugfs_cleanup(struct drm_minor *minor)
 {
-	struct msm_drm_private *priv = minor->dev->dev_private;
-	struct msm_rd_state *rd = priv->rd;
+	struct msm_drm_private *priv;
+	struct msm_rd_state *rd;
+
+	if (!minor || !minor->dev || !minor->dev->dev_private)
+		return;
+
+	priv = minor->dev->dev_private;
+	rd = priv->rd;
 
 	if (!rd)
 		return;
@@ -315,13 +357,20 @@
 /* called under struct_mutex */
 void msm_rd_dump_submit(struct msm_gem_submit *submit)
 {
-	struct drm_device *dev = submit->dev;
-	struct msm_drm_private *priv = dev->dev_private;
-	struct msm_rd_state *rd = priv->rd;
+	struct drm_device *dev;
+	struct msm_drm_private *priv;
+	struct msm_rd_state *rd;
 	char msg[128];
 	int i, n;
 
-	if (!rd->open)
+	if (!submit || !submit->dev || !submit->dev->dev_private)
+		return;
+
+	dev = submit->dev;
+	priv = dev->dev_private;
+	rd = priv->rd;
+
+	if (!rd || !rd->open)
 		return;
 
 	/* writing into fifo is serialized by caller, and
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index df099d3..5cb84b4 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -391,10 +391,24 @@
 			phys_enc);
 }
 
+static bool _sde_encoder_phys_is_ppsplit(struct sde_encoder_phys *phys_enc)
+{
+	enum sde_rm_topology_name topology;
+
+	if (!phys_enc)
+		return false;
+
+	topology = sde_connector_get_topology_name(phys_enc->connector);
+	if (topology == SDE_RM_TOPOLOGY_PPSPLIT)
+		return true;
+
+	return false;
+}
+
 static bool sde_encoder_phys_vid_needs_single_flush(
 		struct sde_encoder_phys *phys_enc)
 {
-	return phys_enc && phys_enc->split_role != ENC_ROLE_SOLO;
+	return phys_enc && _sde_encoder_phys_is_ppsplit(phys_enc);
 }
 
 static int sde_encoder_phys_vid_register_irq(struct sde_encoder_phys *phys_enc,
@@ -680,7 +694,7 @@
 			KICKOFF_TIMEOUT_MS);
 	if (ret <= 0) {
 		irq_status = sde_core_irq_read(phys_enc->sde_kms,
-				INTR_IDX_VSYNC, true);
+				vid_enc->irq_idx[INTR_IDX_VSYNC], true);
 		if (irq_status) {
 			SDE_EVT32(DRMID(phys_enc->parent),
 					vid_enc->hw_intf->idx - INTF_0);
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index f35d77b..1f770c3 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -387,6 +387,8 @@
 
 	} else if (rsc->hw_ops.state_update) {
 		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_IDLE_STATE);
+		if (!rc)
+			rpmh_mode_solver_set(rsc->disp_rsc, false);
 	}
 
 	return rc;
@@ -419,8 +421,11 @@
 		if (client->current_state == SDE_RSC_VID_STATE)
 			goto end;
 
-	if (rsc->hw_ops.state_update)
+	if (rsc->hw_ops.state_update) {
 		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_CMD_STATE);
+		if (!rc)
+			rpmh_mode_solver_set(rsc->disp_rsc, true);
+	}
 
 	/* wait for vsync for vid to cmd state switch */
 	if (!rc && (rsc->current_state == SDE_RSC_VID_STATE))
@@ -440,8 +445,11 @@
 		    (client->current_state == SDE_RSC_CMD_STATE))
 			goto end;
 
-	if (rsc->hw_ops.state_update)
+	if (rsc->hw_ops.state_update) {
 		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_CLK_STATE);
+		if (!rc)
+			rpmh_mode_solver_set(rsc->disp_rsc, false);
+	}
 
 	/* wait for vsync for cmd to clk state switch */
 	if (!rc && rsc->primary_client &&
@@ -463,8 +471,11 @@
 		sde_rsc_timer_calculate(rsc, config);
 
 	/* video state switch should be done immediately */
-	if (rsc->hw_ops.state_update)
+	if (rsc->hw_ops.state_update) {
 		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_VID_STATE);
+		if (!rc)
+			rpmh_mode_solver_set(rsc->disp_rsc, false);
+	}
 
 	/* wait for vsync for cmd to vid state switch */
 	if (!rc && rsc->primary_client &&
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index 69b639a..14a19a4 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.h
@@ -111,14 +111,6 @@
 #define A6XX_VSC_ADDR_MODE_CNTL          0xC01
 
 /* RBBM registers */
-#define A6XX_RBBM_VBIF_CLIENT_QOS_CNTL           0x10
-#define A6XX_RBBM_INTERFACE_HANG_INT_CNTL        0x1f
-#define A6XX_RBBM_INT_CLEAR_CMD                  0x37
-#define A6XX_RBBM_INT_0_MASK                     0x38
-#define A6XX_RBBM_SW_RESET_CMD                   0x43
-#define A6XX_RBBM_BLOCK_SW_RESET_CMD             0x45
-#define A6XX_RBBM_BLOCK_SW_RESET_CMD2            0x46
-#define A6XX_RBBM_CLOCK_CNTL                     0xAE
 #define A6XX_RBBM_INT_0_STATUS                   0x201
 #define A6XX_RBBM_STATUS                         0x210
 #define A6XX_RBBM_STATUS3                        0x213
@@ -390,6 +382,8 @@
 #define A6XX_RBBM_PERFCTR_RBBM_SEL_2             0x509
 #define A6XX_RBBM_PERFCTR_RBBM_SEL_3             0x50A
 
+#define A6XX_RBBM_ISDB_CNT                       0x533
+
 #define A6XX_RBBM_SECVID_TRUST_CNTL              0xF400
 #define A6XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO     0xF800
 #define A6XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI     0xF801
@@ -397,6 +391,122 @@
 #define A6XX_RBBM_SECVID_TSB_CNTL                0xF803
 #define A6XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL      0xF810
 
+#define A6XX_RBBM_VBIF_CLIENT_QOS_CNTL   0x00010
+#define A6XX_RBBM_INTERFACE_HANG_INT_CNTL 0x0001f
+#define A6XX_RBBM_INT_CLEAR_CMD          0x00037
+#define A6XX_RBBM_INT_0_MASK             0x00038
+#define A6XX_RBBM_SP_HYST_CNT            0x00042
+#define A6XX_RBBM_SW_RESET_CMD           0x00043
+#define A6XX_RBBM_RAC_THRESHOLD_CNT      0x00044
+#define A6XX_RBBM_BLOCK_SW_RESET_CMD     0x00045
+#define A6XX_RBBM_BLOCK_SW_RESET_CMD2    0x00046
+#define A6XX_RBBM_CLOCK_CNTL             0x000ae
+#define A6XX_RBBM_CLOCK_CNTL_SP0         0x000b0
+#define A6XX_RBBM_CLOCK_CNTL_SP1         0x000b1
+#define A6XX_RBBM_CLOCK_CNTL_SP2         0x000b2
+#define A6XX_RBBM_CLOCK_CNTL_SP3         0x000b3
+#define A6XX_RBBM_CLOCK_CNTL2_SP0        0x000b4
+#define A6XX_RBBM_CLOCK_CNTL2_SP1        0x000b5
+#define A6XX_RBBM_CLOCK_CNTL2_SP2        0x000b6
+#define A6XX_RBBM_CLOCK_CNTL2_SP3        0x000b7
+#define A6XX_RBBM_CLOCK_DELAY_SP0        0x000b8
+#define A6XX_RBBM_CLOCK_DELAY_SP1        0x000b9
+#define A6XX_RBBM_CLOCK_DELAY_SP2        0x000ba
+#define A6XX_RBBM_CLOCK_DELAY_SP3        0x000bb
+#define A6XX_RBBM_CLOCK_HYST_SP0         0x000bc
+#define A6XX_RBBM_CLOCK_HYST_SP1         0x000bd
+#define A6XX_RBBM_CLOCK_HYST_SP2         0x000be
+#define A6XX_RBBM_CLOCK_HYST_SP3         0x000bf
+#define A6XX_RBBM_CLOCK_CNTL_TP0         0x000c0
+#define A6XX_RBBM_CLOCK_CNTL_TP1         0x000c1
+#define A6XX_RBBM_CLOCK_CNTL_TP2         0x000c2
+#define A6XX_RBBM_CLOCK_CNTL_TP3         0x000c3
+#define A6XX_RBBM_CLOCK_CNTL2_TP0        0x000c4
+#define A6XX_RBBM_CLOCK_CNTL2_TP1        0x000c5
+#define A6XX_RBBM_CLOCK_CNTL2_TP2        0x000c6
+#define A6XX_RBBM_CLOCK_CNTL2_TP3        0x000c7
+#define A6XX_RBBM_CLOCK_CNTL3_TP0        0x000c8
+#define A6XX_RBBM_CLOCK_CNTL3_TP1        0x000c9
+#define A6XX_RBBM_CLOCK_CNTL3_TP2        0x000ca
+#define A6XX_RBBM_CLOCK_CNTL3_TP3        0x000cb
+#define A6XX_RBBM_CLOCK_CNTL4_TP0        0x000cc
+#define A6XX_RBBM_CLOCK_CNTL4_TP1        0x000cd
+#define A6XX_RBBM_CLOCK_CNTL4_TP2        0x000ce
+#define A6XX_RBBM_CLOCK_CNTL4_TP3        0x000cf
+#define A6XX_RBBM_CLOCK_DELAY_TP0        0x000d0
+#define A6XX_RBBM_CLOCK_DELAY_TP1        0x000d1
+#define A6XX_RBBM_CLOCK_DELAY_TP2        0x000d2
+#define A6XX_RBBM_CLOCK_DELAY_TP3        0x000d3
+#define A6XX_RBBM_CLOCK_DELAY2_TP0       0x000d4
+#define A6XX_RBBM_CLOCK_DELAY2_TP1       0x000d5
+#define A6XX_RBBM_CLOCK_DELAY2_TP2       0x000d6
+#define A6XX_RBBM_CLOCK_DELAY2_TP3       0x000d7
+#define A6XX_RBBM_CLOCK_DELAY3_TP0       0x000d8
+#define A6XX_RBBM_CLOCK_DELAY3_TP1       0x000d9
+#define A6XX_RBBM_CLOCK_DELAY3_TP2       0x000da
+#define A6XX_RBBM_CLOCK_DELAY3_TP3       0x000db
+#define A6XX_RBBM_CLOCK_DELAY4_TP0       0x000dc
+#define A6XX_RBBM_CLOCK_DELAY4_TP1       0x000dd
+#define A6XX_RBBM_CLOCK_DELAY4_TP2       0x000de
+#define A6XX_RBBM_CLOCK_DELAY4_TP3       0x000df
+#define A6XX_RBBM_CLOCK_HYST_TP0         0x000e0
+#define A6XX_RBBM_CLOCK_HYST_TP1         0x000e1
+#define A6XX_RBBM_CLOCK_HYST_TP2         0x000e2
+#define A6XX_RBBM_CLOCK_HYST_TP3         0x000e3
+#define A6XX_RBBM_CLOCK_HYST2_TP0        0x000e4
+#define A6XX_RBBM_CLOCK_HYST2_TP1        0x000e5
+#define A6XX_RBBM_CLOCK_HYST2_TP2        0x000e6
+#define A6XX_RBBM_CLOCK_HYST2_TP3        0x000e7
+#define A6XX_RBBM_CLOCK_HYST3_TP0        0x000e8
+#define A6XX_RBBM_CLOCK_HYST3_TP1        0x000e9
+#define A6XX_RBBM_CLOCK_HYST3_TP2        0x000ea
+#define A6XX_RBBM_CLOCK_HYST3_TP3        0x000eb
+#define A6XX_RBBM_CLOCK_HYST4_TP0        0x000ec
+#define A6XX_RBBM_CLOCK_HYST4_TP1        0x000ed
+#define A6XX_RBBM_CLOCK_HYST4_TP2        0x000ee
+#define A6XX_RBBM_CLOCK_HYST4_TP3        0x000ef
+#define A6XX_RBBM_CLOCK_CNTL_RB0         0x000f0
+#define A6XX_RBBM_CLOCK_CNTL_RB1         0x000f1
+#define A6XX_RBBM_CLOCK_CNTL_RB2         0x000f2
+#define A6XX_RBBM_CLOCK_CNTL_RB3         0x000f3
+#define A6XX_RBBM_CLOCK_CNTL2_RB0        0x000f4
+#define A6XX_RBBM_CLOCK_CNTL2_RB1        0x000f5
+#define A6XX_RBBM_CLOCK_CNTL2_RB2        0x000f6
+#define A6XX_RBBM_CLOCK_CNTL2_RB3        0x000f7
+#define A6XX_RBBM_CLOCK_CNTL_CCU0        0x000f8
+#define A6XX_RBBM_CLOCK_CNTL_CCU1        0x000f9
+#define A6XX_RBBM_CLOCK_CNTL_CCU2        0x000fa
+#define A6XX_RBBM_CLOCK_CNTL_CCU3        0x000fb
+#define A6XX_RBBM_CLOCK_HYST_RB_CCU0     0x00100
+#define A6XX_RBBM_CLOCK_HYST_RB_CCU1     0x00101
+#define A6XX_RBBM_CLOCK_HYST_RB_CCU2     0x00102
+#define A6XX_RBBM_CLOCK_HYST_RB_CCU3     0x00103
+#define A6XX_RBBM_CLOCK_CNTL_RAC         0x00104
+#define A6XX_RBBM_CLOCK_CNTL2_RAC        0x00105
+#define A6XX_RBBM_CLOCK_DELAY_RAC        0x00106
+#define A6XX_RBBM_CLOCK_HYST_RAC         0x00107
+#define A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM 0x00108
+#define A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM 0x00109
+#define A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM 0x0010a
+#define A6XX_RBBM_CLOCK_CNTL_UCHE        0x0010b
+#define A6XX_RBBM_CLOCK_CNTL2_UCHE       0x0010c
+#define A6XX_RBBM_CLOCK_CNTL3_UCHE       0x0010d
+#define A6XX_RBBM_CLOCK_CNTL4_UCHE       0x0010e
+#define A6XX_RBBM_CLOCK_DELAY_UCHE       0x0010f
+#define A6XX_RBBM_CLOCK_HYST_UCHE        0x00110
+#define A6XX_RBBM_CLOCK_MODE_VFD         0x00111
+#define A6XX_RBBM_CLOCK_DELAY_VFD        0x00112
+#define A6XX_RBBM_CLOCK_HYST_VFD         0x00113
+#define A6XX_RBBM_CLOCK_MODE_GPC         0x00114
+#define A6XX_RBBM_CLOCK_DELAY_GPC        0x00115
+#define A6XX_RBBM_CLOCK_HYST_GPC         0x00116
+#define A6XX_RBBM_CLOCK_DELAY_HLSQ_2	 0x00117
+#define A6XX_RBBM_CLOCK_CNTL_GMU_GX      0x00118
+#define A6XX_RBBM_CLOCK_DELAY_GMU_GX     0x00119
+#define A6XX_RBBM_CLOCK_HYST_GMU_GX      0x0011a
+#define A6XX_RBBM_CLOCK_MODE_HLSQ	 0x0011b
+#define A6XX_RBBM_CLOCK_DELAY_HLSQ       0x0011c
+
 /* DBGC_CFG registers */
 #define A6XX_DBGC_CFG_DBGBUS_SEL_A                  0x600
 #define A6XX_DBGC_CFG_DBGBUS_SEL_B                  0x601
@@ -666,6 +776,7 @@
 #define A6XX_CX_DBGC_CFG_DBGBUS_SEL_PING_BLK_SEL_SHIFT  0x8
 
 /* GMU control registers */
+#define A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL   0x1A880
 #define A6XX_GMU_GX_SPTPRAC_POWER_CONTROL	0x1A881
 #define A6XX_GMU_CM3_ITCM_START			0x1B400
 #define A6XX_GMU_CM3_DTCM_START			0x1C400
@@ -722,6 +833,9 @@
 #define A6XX_GMU_AO_HOST_INTERRUPT_CLR		0x23B04
 #define A6XX_GMU_AO_HOST_INTERRUPT_STATUS	0x23B05
 #define A6XX_GMU_AO_HOST_INTERRUPT_MASK		0x23B06
+#define A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL       0x23B09
+#define A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL      0x23B0A
+#define A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL       0x23B0B
 #define A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS	0x23B0C
 #define A6XX_GMU_AHB_FENCE_STATUS		0x23B13
 #define A6XX_GMU_RBBM_INT_UNMASKED_STATUS	0x23B15
diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h
index 876ff0c..9a44f34 100644
--- a/drivers/gpu/msm/adreno-gpulist.h
+++ b/drivers/gpu/msm/adreno-gpulist.h
@@ -326,8 +326,7 @@
 		.major = 3,
 		.minor = 0,
 		.patchid = ANY_ID,
-		.features = ADRENO_64BIT |
-			ADRENO_GPMU | ADRENO_RPMH,
+		.features = ADRENO_64BIT | ADRENO_RPMH,
 		.sqefw_name = "a630_sqe.fw",
 		.zap_name = "a630_zap",
 		.gpudev = &adreno_a6xx_gpudev,
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index fb41f95..b5546ef 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -59,6 +59,127 @@
 	{ adreno_is_a630, a630_vbif },
 };
 
+
+struct kgsl_hwcg_reg {
+	unsigned int off;
+	unsigned int val;
+};
+static const struct kgsl_hwcg_reg a630_hwcg_regs[] = {
+	{A6XX_RBBM_CLOCK_CNTL_SP0, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL_SP1, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL_SP2, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL_SP3, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+	{A6XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220},
+	{A6XX_RBBM_CLOCK_CNTL2_SP2, 0x02222220},
+	{A6XX_RBBM_CLOCK_CNTL2_SP3, 0x02222220},
+	{A6XX_RBBM_CLOCK_DELAY_SP0, 0x0000F3CF},
+	{A6XX_RBBM_CLOCK_DELAY_SP1, 0x0000F3CF},
+	{A6XX_RBBM_CLOCK_DELAY_SP2, 0x0000F3CF},
+	{A6XX_RBBM_CLOCK_DELAY_SP3, 0x0000F3CF},
+	{A6XX_RBBM_CLOCK_HYST_SP0, 0x00000080},
+	{A6XX_RBBM_CLOCK_HYST_SP1, 0x00000080},
+	{A6XX_RBBM_CLOCK_HYST_SP2, 0x00000080},
+	{A6XX_RBBM_CLOCK_HYST_SP3, 0x00000080},
+	{A6XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL_TP1, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL_TP2, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL_TP3, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL3_TP0, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL3_TP1, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL3_TP2, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL3_TP3, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL4_TP0, 0x00022222},
+	{A6XX_RBBM_CLOCK_CNTL4_TP1, 0x00022222},
+	{A6XX_RBBM_CLOCK_CNTL4_TP2, 0x00022222},
+	{A6XX_RBBM_CLOCK_CNTL4_TP3, 0x00022222},
+	{A6XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+	{A6XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
+	{A6XX_RBBM_CLOCK_HYST_TP2, 0x77777777},
+	{A6XX_RBBM_CLOCK_HYST_TP3, 0x77777777},
+	{A6XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+	{A6XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
+	{A6XX_RBBM_CLOCK_HYST2_TP2, 0x77777777},
+	{A6XX_RBBM_CLOCK_HYST2_TP3, 0x77777777},
+	{A6XX_RBBM_CLOCK_HYST3_TP0, 0x07777777},
+	{A6XX_RBBM_CLOCK_HYST3_TP1, 0x07777777},
+	{A6XX_RBBM_CLOCK_HYST3_TP2, 0x07777777},
+	{A6XX_RBBM_CLOCK_HYST3_TP3, 0x07777777},
+	{A6XX_RBBM_CLOCK_HYST4_TP0, 0x00077777},
+	{A6XX_RBBM_CLOCK_HYST4_TP1, 0x00077777},
+	{A6XX_RBBM_CLOCK_HYST4_TP2, 0x00077777},
+	{A6XX_RBBM_CLOCK_HYST4_TP3, 0x00077777},
+	{A6XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY_TP2, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY_TP3, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY3_TP0, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY3_TP1, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY3_TP2, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY3_TP3, 0x11111111},
+	{A6XX_RBBM_CLOCK_DELAY4_TP0, 0x00011111},
+	{A6XX_RBBM_CLOCK_DELAY4_TP1, 0x00011111},
+	{A6XX_RBBM_CLOCK_DELAY4_TP2, 0x00011111},
+	{A6XX_RBBM_CLOCK_DELAY4_TP3, 0x00011111},
+	{A6XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
+	{A6XX_RBBM_CLOCK_HYST_UCHE, 0x00000004},
+	{A6XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+	{A6XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL_RB1, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL_RB2, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL_RB3, 0x22222222},
+	{A6XX_RBBM_CLOCK_CNTL2_RB0, 0x00002222},
+	{A6XX_RBBM_CLOCK_CNTL2_RB1, 0x00002222},
+	{A6XX_RBBM_CLOCK_CNTL2_RB2, 0x00002222},
+	{A6XX_RBBM_CLOCK_CNTL2_RB3, 0x00002222},
+	{A6XX_RBBM_CLOCK_CNTL_CCU0, 0x00002220},
+	{A6XX_RBBM_CLOCK_CNTL_CCU1, 0x00002220},
+	{A6XX_RBBM_CLOCK_CNTL_CCU2, 0x00002220},
+	{A6XX_RBBM_CLOCK_CNTL_CCU3, 0x00002220},
+	{A6XX_RBBM_CLOCK_HYST_RB_CCU0, 0x00040F00},
+	{A6XX_RBBM_CLOCK_HYST_RB_CCU1, 0x00040F00},
+	{A6XX_RBBM_CLOCK_HYST_RB_CCU2, 0x00040F00},
+	{A6XX_RBBM_CLOCK_HYST_RB_CCU3, 0x00040F00},
+	{A6XX_RBBM_CLOCK_CNTL_RAC, 0x05022022},
+	{A6XX_RBBM_CLOCK_CNTL2_RAC, 0x00005555},
+	{A6XX_RBBM_CLOCK_DELAY_RAC, 0x00010011},
+	{A6XX_RBBM_CLOCK_HYST_RAC, 0x00445044},
+	{A6XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+	{A6XX_RBBM_CLOCK_MODE_GPC, 0x02222222},
+	{A6XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+	{A6XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+	{A6XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+	{A6XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+	{A6XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+	{A6XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+	{A6XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+	{A6XX_RBBM_CLOCK_DELAY_VFD, 0x00002222},
+	{A6XX_RBBM_CLOCK_DELAY_HLSQ_2, 0x00000002},
+	{A6XX_RBBM_CLOCK_MODE_HLSQ, 0x00002222},
+	{A6XX_RBBM_CLOCK_CNTL_GMU_GX, 0x00000222},
+	{A6XX_RBBM_CLOCK_DELAY_GMU_GX, 0x00000111},
+	{A6XX_RBBM_CLOCK_HYST_GMU_GX, 0x00000555}
+};
+
+static const struct {
+	int (*devfunc)(struct adreno_device *adreno_dev);
+	const struct kgsl_hwcg_reg *regs;
+	unsigned int count;
+} a6xx_hwcg_registers[] = {
+	{adreno_is_a630, a630_hwcg_regs, ARRAY_SIZE(a630_hwcg_regs)}
+};
+
 static struct a6xx_protected_regs {
 	unsigned int base;
 	unsigned int count;
@@ -181,6 +302,48 @@
 	kgsl_regwrite(device, A6XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL, 0x1);
 }
 
+
+static void a6xx_hwcg_set(struct adreno_device *adreno_dev, bool on)
+{
+	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
+	const struct kgsl_hwcg_reg *regs;
+	int i, j;
+
+	if (!test_bit(ADRENO_HWCG_CTRL, &adreno_dev->pwrctrl_flag))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(a6xx_hwcg_registers); i++) {
+		if (a6xx_hwcg_registers[i].devfunc(adreno_dev))
+			break;
+	}
+
+	if (i == ARRAY_SIZE(a6xx_hwcg_registers))
+		return;
+
+	regs = a6xx_hwcg_registers[i].regs;
+
+	/* Disable SP clock before programming HWCG registers */
+	kgsl_gmu_regrmw(device, A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 0, 0);
+
+	for (j = 0; j < a6xx_hwcg_registers[i].count; j++)
+		kgsl_regwrite(device, regs[j].off, on ? regs[j].val : 0);
+
+	if (kgsl_gmu_isenabled(device)) {
+		kgsl_gmu_regwrite(device, A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL,
+			0x00020222);
+		kgsl_gmu_regwrite(device, A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL,
+			0x00010111);
+		kgsl_gmu_regwrite(device, A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL,
+			0x00050555);
+	}
+	/* Enable SP clock */
+	kgsl_gmu_regrmw(device, A6XX_GPU_GMU_GX_SPTPRAC_CLOCK_CONTROL, 0, 1);
+
+	/* enable top level HWCG */
+	kgsl_regwrite(device, A6XX_RBBM_CLOCK_CNTL, on ? 0x8AA8AA02 : 0);
+	kgsl_regwrite(device, A5XX_RBBM_ISDB_CNT, on ? 0x00000182 : 0x00000180);
+}
+
 /*
  * a6xx_start() - Device start
  * @adreno_dev: Pointer to adreno device
@@ -197,6 +360,8 @@
 	if (!kgsl_gmu_isenabled(device))
 		/* Legacy idle management if gmu is disabled */
 		ADRENO_GPU_DEVICE(adreno_dev)->hw_isidle = NULL;
+	/* enable hardware clockgating */
+	a6xx_hwcg_set(adreno_dev, true);
 
 	adreno_vbif_start(adreno_dev, a6xx_vbif_platforms,
 			ARRAY_SIZE(a6xx_vbif_platforms));
@@ -1557,7 +1722,10 @@
 	else if (client_id != 3)
 		return fault_block[client_id];
 
+	mutex_lock(&device->mutex);
 	kgsl_regread(device, A6XX_UCHE_CLIENT_PF, &uche_client_id);
+	mutex_unlock(&device->mutex);
+
 	return uche_client[uche_client_id & A6XX_UCHE_CLIENT_PF_CLIENT_ID_MASK];
 }
 
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index ba83cd7..01ecb01 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -121,6 +121,8 @@
 	unsigned int statetype;
 	const unsigned int *regs;
 	unsigned int num_sets;
+	unsigned int offset0;
+	unsigned int offset1;
 } a6xx_dbgahb_ctx_clusters[] = {
 	{ CP_CLUSTER_SP_VS, 0x0002E000, 0x41, a6xx_sp_vs_hlsq_cluster,
 		ARRAY_SIZE(a6xx_sp_vs_hlsq_cluster) / 2 },
@@ -624,8 +626,8 @@
 	return val;
 }
 
-static size_t a6xx_snapshot_cluster_dbgahb(struct kgsl_device *device, u8 *buf,
-				size_t remain, void *priv)
+static size_t a6xx_legacy_snapshot_cluster_dbgahb(struct kgsl_device *device,
+				u8 *buf, size_t remain, void *priv)
 {
 	struct kgsl_snapshot_mvc_regs *header =
 				(struct kgsl_snapshot_mvc_regs *)buf;
@@ -678,6 +680,63 @@
 	return data_size + sizeof(*header);
 }
 
+static size_t a6xx_snapshot_cluster_dbgahb(struct kgsl_device *device, u8 *buf,
+				size_t remain, void *priv)
+{
+	struct kgsl_snapshot_mvc_regs *header =
+				(struct kgsl_snapshot_mvc_regs *)buf;
+	struct a6xx_cluster_dbgahb_regs_info *info =
+				(struct a6xx_cluster_dbgahb_regs_info *)priv;
+	struct a6xx_cluster_dbgahb_registers *cluster = info->cluster;
+	unsigned int data_size = 0;
+	unsigned int *data = (unsigned int *)(buf + sizeof(*header));
+	int i, j;
+	unsigned int *src;
+
+
+	if (crash_dump_valid == false)
+		return a6xx_legacy_snapshot_cluster_dbgahb(device, buf, remain,
+				info);
+
+	if (remain < sizeof(*header)) {
+		SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
+		return 0;
+	}
+
+	remain -= sizeof(*header);
+
+	header->ctxt_id = info->ctxt_id;
+	header->cluster_id = cluster->id;
+
+	src = (unsigned int *)(a6xx_crashdump_registers.hostptr +
+		(header->ctxt_id ? cluster->offset1 : cluster->offset0));
+
+	for (i = 0; i < cluster->num_sets; i++) {
+		unsigned int start;
+		unsigned int end;
+
+		start = cluster->regs[2 * i];
+		end = cluster->regs[2 * i + 1];
+
+		if (remain < (end - start + 3) * 4) {
+			SNAPSHOT_ERR_NOMEM(device, "MVC REGISTERS");
+			goto out;
+		}
+
+		remain -= (end - start + 3) * 4;
+		data_size += (end - start + 3) * 4;
+
+		*data++ = start | (1 << 31);
+		*data++ = end;
+		for (j = start; j <= end; j++)
+			*data++ = *src++;
+	}
+out:
+	return data_size + sizeof(*header);
+}
+
+
+
 static size_t a6xx_snapshot_non_ctx_dbgahb(struct kgsl_device *device, u8 *buf,
 				size_t remain, void *priv)
 {
@@ -1391,6 +1450,47 @@
 	return qwords;
 }
 
+static int _a6xx_crashdump_init_ctx_dbgahb(uint64_t *ptr, uint64_t *offset)
+{
+	int qwords = 0;
+	unsigned int i, j, k;
+	unsigned int count;
+
+	for (i = 0; i < ARRAY_SIZE(a6xx_dbgahb_ctx_clusters); i++) {
+		struct a6xx_cluster_dbgahb_registers *cluster =
+				&a6xx_dbgahb_ctx_clusters[i];
+
+		cluster->offset0 = *offset;
+
+		for (j = 0; j < A6XX_NUM_CTXTS; j++) {
+			if (j == 1)
+				cluster->offset1 = *offset;
+
+			/* Program the aperture */
+			ptr[qwords++] =
+				((cluster->statetype + j * 2) & 0xff) << 8;
+			ptr[qwords++] =
+				(((uint64_t)A6XX_HLSQ_DBG_READ_SEL << 44)) |
+					(1 << 21) | 1;
+
+			for (k = 0; k < cluster->num_sets; k++) {
+				unsigned int start = cluster->regs[2 * k];
+
+				count = REG_PAIR_COUNT(cluster->regs, k);
+				ptr[qwords++] =
+				a6xx_crashdump_registers.gpuaddr + *offset;
+				ptr[qwords++] =
+				(((uint64_t)(A6XX_HLSQ_DBG_AHB_READ_APERTURE +
+					start - cluster->regbase / 4) << 44)) |
+							count;
+
+				*offset += count * sizeof(unsigned int);
+			}
+		}
+	}
+	return qwords;
+}
+
 void a6xx_crashdump_init(struct adreno_device *adreno_dev)
 {
 	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
@@ -1458,6 +1558,26 @@
 		}
 	}
 
+	/* Calculate the script and data size for debug AHB registers */
+	for (i = 0; i < ARRAY_SIZE(a6xx_dbgahb_ctx_clusters); i++) {
+		struct a6xx_cluster_dbgahb_registers *cluster =
+				&a6xx_dbgahb_ctx_clusters[i];
+
+		for (j = 0; j < A6XX_NUM_CTXTS; j++) {
+
+			/* 16 bytes for programming the aperture */
+			script_size += 16;
+
+			/* Reading each pair of registers takes 16 bytes */
+			script_size += 16 * cluster->num_sets;
+
+			/* A dword per register read from the cluster list */
+			for (k = 0; k < cluster->num_sets; k++)
+				data_size += REG_PAIR_COUNT(cluster->regs, k) *
+						sizeof(unsigned int);
+		}
+	}
+
 	/* Now allocate the script and data buffers */
 
 	/* The script buffers needs 2 extra qwords on the end */
@@ -1497,6 +1617,8 @@
 	/* Program the capturescript for the MVC regsiters */
 	ptr += _a6xx_crashdump_init_mvc(ptr, &offset);
 
+	ptr += _a6xx_crashdump_init_ctx_dbgahb(ptr, &offset);
+
 	*ptr++ = 0;
 	*ptr++ = 0;
 }
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 25eab45..e7b96f1 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -685,6 +685,13 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
 		},
 	},
+	{
+		/* Clevo P650RS, 650RP6, Sager NP8152-S, and others */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"),
+		},
+	},
 	{ }
 };
 
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 261c125..7f9d9e1 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1770,3 +1770,16 @@
 	*id = fwspec->ids[0];
 	return 0;
 }
+
+/*
+ * Until a formal solution for probe deferral becomes part
+ * of the iommu framework...
+ */
+int iommu_is_available(struct device *dev)
+{
+	if (!dev->bus->iommu_ops ||
+		!dev->iommu_fwspec ||
+		!dev->iommu_group)
+		return -EPROBE_DEFER;
+	return 0;
+}
diff --git a/drivers/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c
index 3060cfa..cb19cef 100644
--- a/drivers/leds/leds-qpnp-wled.c
+++ b/drivers/leds/leds-qpnp-wled.c
@@ -2264,7 +2264,7 @@
 {
 	return platform_driver_register(&qpnp_wled_driver);
 }
-module_init(qpnp_wled_init);
+subsys_initcall(qpnp_wled_init);
 
 static void __exit qpnp_wled_exit(void)
 {
diff --git a/drivers/mailbox/qti-tcs.c b/drivers/mailbox/qti-tcs.c
index dfed3cd..6d0e913 100644
--- a/drivers/mailbox/qti-tcs.c
+++ b/drivers/mailbox/qti-tcs.c
@@ -333,6 +333,20 @@
 	tasklet_schedule(&resp->tasklet);
 }
 
+static inline void enable_tcs_irq(struct tcs_drv *drv, int m, bool enable)
+{
+	void __iomem *base = drv->reg_base;
+	u32 data;
+
+	/* Enable interrupts for non-ACTIVE TCS */
+	data = read_tcs_reg(base, TCS_DRV_IRQ_ENABLE, 0, 0);
+	if (enable)
+		data |= BIT(m);
+	else
+		data &= ~BIT(m);
+	write_tcs_reg(base, TCS_DRV_IRQ_ENABLE, 0, 0, data);
+}
+
 /**
  * tcs_irq_handler: TX Done / Recv data handler
  */
@@ -350,10 +364,9 @@
 	/* Know which TCSes were triggered */
 	irq_status = read_tcs_reg(base, TCS_DRV_IRQ_STATUS, 0, 0);
 
-	for (m = 0; irq_status >= BIT(m); m++) {
-		if (!(irq_status & BIT(m)))
+	for (m = 0; m < drv->num_tcs; m++) {
+		if (!(irq_status & (u32)BIT(m)))
 			continue;
-
 		atomic_inc(&drv->tcs_irq_count[m]);
 
 		resp = get_response(drv, m);
@@ -395,6 +408,12 @@
 			data = read_tcs_reg(base, TCS_DRV_CONTROL, m, 0);
 			data &= ~TCS_AMC_MODE_ENABLE;
 			write_tcs_reg(base, TCS_DRV_CONTROL, m, 0, data);
+			/*
+			 * Disable interrupt for this TCS to avoid being
+			 * spammed with interrupts coming when the solver
+			 * sends its wake votes.
+			 */
+			enable_tcs_irq(drv, m, false);
 		} else {
 			/* Clear the enable bit for the commands */
 			write_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0, 0);
@@ -523,9 +542,11 @@
 			continue;
 
 		curr_enabled = read_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0);
-		for (j = 0; j < curr_enabled; j++) {
-			if (!(curr_enabled & BIT(j)))
+
+		for (j = 0; j < MAX_CMDS_PER_TCS; j++) {
+			if (!(curr_enabled & (u32)BIT(j)))
 				continue;
+
 			addr = read_tcs_reg(base, TCS_DRV_CMD_ADDR, m, j);
 			for (k = 0; k < msg->num_payload; k++) {
 				if (addr == msg->payload[k].addr)
@@ -659,6 +680,9 @@
 		/* Mark the TCS as busy */
 		atomic_set(&drv->tcs_in_use[m], 1);
 		atomic_inc(&drv->tcs_send_count[m]);
+		/* Enable interrupt for active votes through wake TCS */
+		if (tcs->type != ACTIVE_TCS)
+			enable_tcs_irq(drv, m, true);
 	}
 
 	/* Write to the TCS or AMC */
@@ -902,7 +926,6 @@
 	u32 config, max_tcs, ncpt;
 	int tcs_type_count[TCS_TYPE_NR] = { 0 };
 	struct resource *res;
-	u32 irq_mask;
 
 	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
 	if (!drv)
@@ -1043,14 +1066,9 @@
 	if (ret)
 		return ret;
 
-	/*
-	 * Enable interrupts for AMC TCS,
-	 * if there are no AMC TCS, use wake TCS.
-	 */
-	irq_mask = (drv->tcs[ACTIVE_TCS].num_tcs) ?
-				drv->tcs[ACTIVE_TCS].tcs_mask :
-				drv->tcs[WAKE_TCS].tcs_mask;
-	write_tcs_reg(drv->reg_base, TCS_DRV_IRQ_ENABLE, 0, 0, irq_mask);
+	/* Enable interrupts for AMC TCS */
+	write_tcs_reg(drv->reg_base, TCS_DRV_IRQ_ENABLE, 0, 0,
+					drv->tcs[ACTIVE_TCS].tcs_mask);
 
 	for (i = 0; i < ARRAY_SIZE(drv->tcs_in_use); i++)
 		atomic_set(&drv->tcs_in_use[i], 0);
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_subdev.c b/drivers/media/platform/msm/camera/cam_core/cam_subdev.c
index 03b18cf..429474b 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_subdev.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_subdev.c
@@ -75,7 +75,26 @@
 static long cam_subdev_compat_ioctl(struct v4l2_subdev *sd,
 	unsigned int cmd, unsigned long arg)
 {
-	return cam_subdev_ioctl(sd, cmd, compat_ptr(arg));
+	struct cam_control cmd_data;
+	int rc;
+
+	if (copy_from_user(&cmd_data, (void __user *)arg,
+		sizeof(cmd_data))) {
+		pr_err("Failed to copy from user_ptr=%pK size=%zu\n",
+			(void __user *)arg, sizeof(cmd_data));
+		return -EFAULT;
+	}
+	rc = cam_subdev_ioctl(sd, cmd, &cmd_data);
+	if (!rc) {
+		if (copy_to_user((void __user *)arg, &cmd_data,
+			sizeof(cmd_data))) {
+			pr_err("Failed to copy to user_ptr=%pK size=%zu\n",
+				(void __user *)arg, sizeof(cmd_data));
+			rc = -EFAULT;
+		}
+	}
+
+	return rc;
 }
 #endif
 
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index f4c636d..598d563 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1974,6 +1974,7 @@
 			/* Enable QP for all frame types by default */
 			qp.enable = 7;
 			qp_range.layer_id = control[i].value;
+			bitrate.layer_id = control[i].value;
 			i++;
 			while (i < ctrl->count) {
 			switch (control[i].id) {
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index adc2147..0898414 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -337,6 +337,7 @@
 		"4.2",
 		"5",
 		"5.1",
+		"5.2",
 		NULL,
 	};
 	static const char * const h264_loop_filter[] = {
@@ -363,6 +364,7 @@
 		"Scalable High Intra",
 		"Stereo High",
 		"Multiview High",
+		"Constrained High",
 		NULL,
 	};
 	static const char * const vui_sar_idc[] = {
diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c
index 3bc7d4e..127a052 100644
--- a/drivers/misc/uid_sys_stats.c
+++ b/drivers/misc/uid_sys_stats.c
@@ -96,9 +96,11 @@
 {
 	struct uid_entry *uid_entry;
 	struct task_struct *task, *temp;
+	struct user_namespace *user_ns = current_user_ns();
 	cputime_t utime;
 	cputime_t stime;
 	unsigned long bkt;
+	uid_t uid;
 
 	rt_mutex_lock(&uid_lock);
 
@@ -109,14 +111,13 @@
 
 	read_lock(&tasklist_lock);
 	do_each_thread(temp, task) {
-		uid_entry = find_or_register_uid(from_kuid_munged(
-			current_user_ns(), task_uid(task)));
+		uid = from_kuid_munged(user_ns, task_uid(task));
+		uid_entry = find_or_register_uid(uid);
 		if (!uid_entry) {
 			read_unlock(&tasklist_lock);
 			rt_mutex_unlock(&uid_lock);
 			pr_err("%s: failed to find the uid_entry for uid %d\n",
-				__func__, from_kuid_munged(current_user_ns(),
-				task_uid(task)));
+				__func__, uid);
 			return -ENOMEM;
 		}
 		task_cputime_adjusted(task, &utime, &stime);
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index a0dabd4..7ab24c5 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -740,13 +740,18 @@
 static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
 {
 	struct gs_can *dev = netdev_priv(netdev);
-	struct gs_identify_mode imode;
+	struct gs_identify_mode *imode;
 	int rc;
 
+	imode = kmalloc(sizeof(*imode), GFP_KERNEL);
+
+	if (!imode)
+		return -ENOMEM;
+
 	if (do_identify)
-		imode.mode = GS_CAN_IDENTIFY_ON;
+		imode->mode = GS_CAN_IDENTIFY_ON;
 	else
-		imode.mode = GS_CAN_IDENTIFY_OFF;
+		imode->mode = GS_CAN_IDENTIFY_OFF;
 
 	rc = usb_control_msg(interface_to_usbdev(dev->iface),
 			     usb_sndctrlpipe(interface_to_usbdev(dev->iface),
@@ -756,10 +761,12 @@
 			     USB_RECIP_INTERFACE,
 			     dev->channel,
 			     0,
-			     &imode,
-			     sizeof(imode),
+			     imode,
+			     sizeof(*imode),
 			     100);
 
+	kfree(imode);
+
 	return (rc > 0) ? 0 : rc;
 }
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 81d8e3b..21ce0b7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -82,7 +82,7 @@
 #define MLX5E_VALID_NUM_MTTS(num_mtts) (MLX5_MTT_OCTW(num_mtts) <= U16_MAX)
 
 #define MLX5_UMR_ALIGN				(2048)
-#define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD	(128)
+#define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD	(256)
 
 #define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ                 (64 * 1024)
 #define MLX5E_DEFAULT_LRO_TIMEOUT                       32
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
index 90e81ae..e034dbc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
@@ -563,6 +563,7 @@
 	int idx = 0;
 	int err = 0;
 
+	info->data = MAX_NUM_OF_ETHTOOL_RULES;
 	while ((!err || err == -ENOENT) && idx < info->rule_cnt) {
 		err = mlx5e_ethtool_get_flow(priv, info, location);
 		if (!err)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c
index 5595724..b5d5519 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c
@@ -294,7 +294,7 @@
 					 struct netdev_notifier_changeupper_info *info)
 {
 	struct net_device *upper = info->upper_dev, *ndev_tmp;
-	struct netdev_lag_upper_info *lag_upper_info;
+	struct netdev_lag_upper_info *lag_upper_info = NULL;
 	bool is_bonded;
 	int bond_status = 0;
 	int num_slaves = 0;
@@ -303,7 +303,8 @@
 	if (!netif_is_lag_master(upper))
 		return 0;
 
-	lag_upper_info = info->upper_info;
+	if (info->linking)
+		lag_upper_info = info->upper_info;
 
 	/* The event may still be of interest if the slave does not belong to
 	 * us, but is enslaved to a master which has one or more of our netdevs
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 7a196a0..d776db7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -966,7 +966,7 @@
 	if (err) {
 		dev_err(&dev->pdev->dev, "Firmware over %d MS in initializing state, aborting\n",
 			FW_INIT_TIMEOUT_MILI);
-		goto out_err;
+		goto err_cmd_cleanup;
 	}
 
 	err = mlx5_core_enable_hca(dev, 0);
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 1a92de7..a2d218b 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1059,12 +1059,70 @@
 	.get_mdio_data = sh_get_mdio,
 };
 
+/* free Tx skb function */
+static int sh_eth_tx_free(struct net_device *ndev, bool sent_only)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	struct sh_eth_txdesc *txdesc;
+	int free_num = 0;
+	int entry;
+	bool sent;
+
+	for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
+		entry = mdp->dirty_tx % mdp->num_tx_ring;
+		txdesc = &mdp->tx_ring[entry];
+		sent = !(txdesc->status & cpu_to_le32(TD_TACT));
+		if (sent_only && !sent)
+			break;
+		/* TACT bit must be checked before all the following reads */
+		dma_rmb();
+		netif_info(mdp, tx_done, ndev,
+			   "tx entry %d status 0x%08x\n",
+			   entry, le32_to_cpu(txdesc->status));
+		/* Free the original skb. */
+		if (mdp->tx_skbuff[entry]) {
+			dma_unmap_single(&ndev->dev, le32_to_cpu(txdesc->addr),
+					 le32_to_cpu(txdesc->len) >> 16,
+					 DMA_TO_DEVICE);
+			dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
+			mdp->tx_skbuff[entry] = NULL;
+			free_num++;
+		}
+		txdesc->status = cpu_to_le32(TD_TFP);
+		if (entry >= mdp->num_tx_ring - 1)
+			txdesc->status |= cpu_to_le32(TD_TDLE);
+
+		if (sent) {
+			ndev->stats.tx_packets++;
+			ndev->stats.tx_bytes += le32_to_cpu(txdesc->len) >> 16;
+		}
+	}
+	return free_num;
+}
+
 /* free skb and descriptor buffer */
 static void sh_eth_ring_free(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	int ringsize, i;
 
+	if (mdp->rx_ring) {
+		for (i = 0; i < mdp->num_rx_ring; i++) {
+			if (mdp->rx_skbuff[i]) {
+				struct sh_eth_rxdesc *rxdesc = &mdp->rx_ring[i];
+
+				dma_unmap_single(&ndev->dev,
+						 le32_to_cpu(rxdesc->addr),
+						 ALIGN(mdp->rx_buf_sz, 32),
+						 DMA_FROM_DEVICE);
+			}
+		}
+		ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
+		dma_free_coherent(NULL, ringsize, mdp->rx_ring,
+				  mdp->rx_desc_dma);
+		mdp->rx_ring = NULL;
+	}
+
 	/* Free Rx skb ringbuffer */
 	if (mdp->rx_skbuff) {
 		for (i = 0; i < mdp->num_rx_ring; i++)
@@ -1073,27 +1131,18 @@
 	kfree(mdp->rx_skbuff);
 	mdp->rx_skbuff = NULL;
 
-	/* Free Tx skb ringbuffer */
-	if (mdp->tx_skbuff) {
-		for (i = 0; i < mdp->num_tx_ring; i++)
-			dev_kfree_skb(mdp->tx_skbuff[i]);
-	}
-	kfree(mdp->tx_skbuff);
-	mdp->tx_skbuff = NULL;
-
-	if (mdp->rx_ring) {
-		ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
-		dma_free_coherent(NULL, ringsize, mdp->rx_ring,
-				  mdp->rx_desc_dma);
-		mdp->rx_ring = NULL;
-	}
-
 	if (mdp->tx_ring) {
+		sh_eth_tx_free(ndev, false);
+
 		ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
 		dma_free_coherent(NULL, ringsize, mdp->tx_ring,
 				  mdp->tx_desc_dma);
 		mdp->tx_ring = NULL;
 	}
+
+	/* Free Tx skb ringbuffer */
+	kfree(mdp->tx_skbuff);
+	mdp->tx_skbuff = NULL;
 }
 
 /* format skb and descriptor buffer */
@@ -1341,43 +1390,6 @@
 	update_mac_address(ndev);
 }
 
-/* free Tx skb function */
-static int sh_eth_txfree(struct net_device *ndev)
-{
-	struct sh_eth_private *mdp = netdev_priv(ndev);
-	struct sh_eth_txdesc *txdesc;
-	int free_num = 0;
-	int entry;
-
-	for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
-		entry = mdp->dirty_tx % mdp->num_tx_ring;
-		txdesc = &mdp->tx_ring[entry];
-		if (txdesc->status & cpu_to_le32(TD_TACT))
-			break;
-		/* TACT bit must be checked before all the following reads */
-		dma_rmb();
-		netif_info(mdp, tx_done, ndev,
-			   "tx entry %d status 0x%08x\n",
-			   entry, le32_to_cpu(txdesc->status));
-		/* Free the original skb. */
-		if (mdp->tx_skbuff[entry]) {
-			dma_unmap_single(&ndev->dev, le32_to_cpu(txdesc->addr),
-					 le32_to_cpu(txdesc->len) >> 16,
-					 DMA_TO_DEVICE);
-			dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
-			mdp->tx_skbuff[entry] = NULL;
-			free_num++;
-		}
-		txdesc->status = cpu_to_le32(TD_TFP);
-		if (entry >= mdp->num_tx_ring - 1)
-			txdesc->status |= cpu_to_le32(TD_TDLE);
-
-		ndev->stats.tx_packets++;
-		ndev->stats.tx_bytes += le32_to_cpu(txdesc->len) >> 16;
-	}
-	return free_num;
-}
-
 /* Packet receive function */
 static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
 {
@@ -1620,7 +1632,7 @@
 			   intr_status, mdp->cur_tx, mdp->dirty_tx,
 			   (u32)ndev->state, edtrr);
 		/* dirty buffer free */
-		sh_eth_txfree(ndev);
+		sh_eth_tx_free(ndev, true);
 
 		/* SH7712 BUG */
 		if (edtrr ^ sh_eth_get_edtrr_trns(mdp)) {
@@ -1679,7 +1691,7 @@
 		/* Clear Tx interrupts */
 		sh_eth_write(ndev, intr_status & cd->tx_check, EESR);
 
-		sh_eth_txfree(ndev);
+		sh_eth_tx_free(ndev, true);
 		netif_wake_queue(ndev);
 	}
 
@@ -2307,7 +2319,7 @@
 
 	spin_lock_irqsave(&mdp->lock, flags);
 	if ((mdp->cur_tx - mdp->dirty_tx) >= (mdp->num_tx_ring - 4)) {
-		if (!sh_eth_txfree(ndev)) {
+		if (!sh_eth_tx_free(ndev, true)) {
 			netif_warn(mdp, tx_queued, ndev, "TxFD exhausted.\n");
 			netif_stop_queue(ndev);
 			spin_unlock_irqrestore(&mdp->lock, flags);
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index d2e61e0..f7c6a40 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -2709,7 +2709,7 @@
 }
 
 #define MACSEC_FEATURES \
-	(NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST)
+	(NETIF_F_SG | NETIF_F_HIGHDMA)
 static struct lock_class_key macsec_netdev_addr_lock_key;
 
 static int macsec_dev_init(struct net_device *dev)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 26d6f0b..dc8ccac 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1140,6 +1140,7 @@
 static void macvlan_port_destroy(struct net_device *dev)
 {
 	struct macvlan_port *port = macvlan_port_get_rtnl(dev);
+	struct sk_buff *skb;
 
 	dev->priv_flags &= ~IFF_MACVLAN_PORT;
 	netdev_rx_handler_unregister(dev);
@@ -1148,7 +1149,15 @@
 	 * but we need to cancel it and purge left skbs if any.
 	 */
 	cancel_work_sync(&port->bc_work);
-	__skb_queue_purge(&port->bc_queue);
+
+	while ((skb = __skb_dequeue(&port->bc_queue))) {
+		const struct macvlan_dev *src = MACVLAN_SKB_CB(skb)->src;
+
+		if (src)
+			dev_put(src->dev);
+
+		kfree_skb(skb);
+	}
 
 	kfree_rcu(port, rcu);
 }
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 7a240fc..4865221 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -1438,8 +1438,6 @@
 		skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
 		skb_queue_tail(&dp83640->rx_queue, skb);
 		schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT);
-	} else {
-		netif_rx_ni(skb);
 	}
 
 	return true;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 201ffa5..a9be26f 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -552,16 +552,18 @@
 EXPORT_SYMBOL(phy_mii_ioctl);
 
 /**
- * phy_start_aneg - start auto-negotiation for this PHY device
+ * phy_start_aneg_priv - start auto-negotiation for this PHY device
  * @phydev: the phy_device struct
+ * @sync: indicate whether we should wait for the workqueue cancelation
  *
  * Description: Sanitizes the settings (if we're not autonegotiating
  *   them), and then calls the driver's config_aneg function.
  *   If the PHYCONTROL Layer is operating, we change the state to
  *   reflect the beginning of Auto-negotiation or forcing.
  */
-int phy_start_aneg(struct phy_device *phydev)
+static int phy_start_aneg_priv(struct phy_device *phydev, bool sync)
 {
+	bool trigger = 0;
 	int err;
 
 	mutex_lock(&phydev->lock);
@@ -586,10 +588,40 @@
 		}
 	}
 
+	/* Re-schedule a PHY state machine to check PHY status because
+	 * negotiation may already be done and aneg interrupt may not be
+	 * generated.
+	 */
+	if (phy_interrupt_is_valid(phydev) && (phydev->state == PHY_AN)) {
+		err = phy_aneg_done(phydev);
+		if (err > 0) {
+			trigger = true;
+			err = 0;
+		}
+	}
+
 out_unlock:
 	mutex_unlock(&phydev->lock);
+
+	if (trigger)
+		phy_trigger_machine(phydev, sync);
+
 	return err;
 }
+
+/**
+ * phy_start_aneg - start auto-negotiation for this PHY device
+ * @phydev: the phy_device struct
+ *
+ * Description: Sanitizes the settings (if we're not autonegotiating
+ *   them), and then calls the driver's config_aneg function.
+ *   If the PHYCONTROL Layer is operating, we change the state to
+ *   reflect the beginning of Auto-negotiation or forcing.
+ */
+int phy_start_aneg(struct phy_device *phydev)
+{
+	return phy_start_aneg_priv(phydev, true);
+}
 EXPORT_SYMBOL(phy_start_aneg);
 
 /**
@@ -617,7 +649,7 @@
  *   state machine runs.
  */
 
-static void phy_trigger_machine(struct phy_device *phydev, bool sync)
+void phy_trigger_machine(struct phy_device *phydev, bool sync)
 {
 	if (sync)
 		cancel_delayed_work_sync(&phydev->state_queue);
@@ -639,7 +671,7 @@
 	cancel_delayed_work_sync(&phydev->state_queue);
 
 	mutex_lock(&phydev->lock);
-	if (phydev->state > PHY_UP)
+	if (phydev->state > PHY_UP && phydev->state != PHY_HALTED)
 		phydev->state = PHY_UP;
 	mutex_unlock(&phydev->lock);
 }
@@ -1100,7 +1132,7 @@
 	mutex_unlock(&phydev->lock);
 
 	if (needs_aneg)
-		err = phy_start_aneg(phydev);
+		err = phy_start_aneg_priv(phydev, false);
 	else if (do_suspend)
 		phy_suspend(phydev);
 
diff --git a/drivers/net/ppp/pppolac.c b/drivers/net/ppp/pppolac.c
index 0184c96..3a45cf8 100644
--- a/drivers/net/ppp/pppolac.c
+++ b/drivers/net/ppp/pppolac.c
@@ -206,7 +206,9 @@
 	while ((skb = skb_dequeue(&delivery_queue))) {
 		struct sock *sk_udp = skb->sk;
 		struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
-		struct msghdr msg = { 0 };
+		struct msghdr msg = {
+			.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
+		};
 
 		iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1,
 			      skb->len);
diff --git a/drivers/net/ppp/pppopns.c b/drivers/net/ppp/pppopns.c
index d9e0603..cdb4fa1 100644
--- a/drivers/net/ppp/pppopns.c
+++ b/drivers/net/ppp/pppopns.c
@@ -189,7 +189,9 @@
 	while ((skb = skb_dequeue(&delivery_queue))) {
 		struct sock *sk_raw = skb->sk;
 		struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
-		struct msghdr msg = { 0 };
+		struct msghdr msg = {
+			.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
+		};
 
 		iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1,
 			      skb->len);
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index a2afb8e..80ef486 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1124,7 +1124,7 @@
 		goto nla_put_failure;
 
 	/* rule only needs to appear once */
-	nlh->nlmsg_flags &= NLM_F_EXCL;
+	nlh->nlmsg_flags |= NLM_F_EXCL;
 
 	frh = nlmsg_data(nlh);
 	memset(frh, 0, sizeof(*frh));
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 6c68fd9..4e111cb 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -474,22 +474,23 @@
 	}
 	mutex_unlock(&wil->p2p_wdev_mutex);
 
-	/* social scan on P2P_DEVICE is handled as p2p search */
-	if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE &&
-	    wil_p2p_is_social_scan(request)) {
+	if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
 		if (!wil->p2p.p2p_dev_started) {
 			wil_err(wil, "P2P search requested on stopped P2P device\n");
 			rc = -EIO;
 			goto out;
 		}
-		wil->scan_request = request;
-		wil->radio_wdev = wdev;
-		rc = wil_p2p_search(wil, request);
-		if (rc) {
-			wil->radio_wdev = wil_to_wdev(wil);
-			wil->scan_request = NULL;
+		/* social scan on P2P_DEVICE is handled as p2p search */
+		if (wil_p2p_is_social_scan(request)) {
+			wil->scan_request = request;
+			wil->radio_wdev = wdev;
+			rc = wil_p2p_search(wil, request);
+			if (rc) {
+				wil->radio_wdev = wil_to_wdev(wil);
+				wil->scan_request = NULL;
+			}
+			goto out;
 		}
-		goto out;
 	}
 
 	(void)wil_p2p_stop_discovery(wil);
@@ -499,9 +500,9 @@
 
 	for (i = 0; i < request->n_ssids; i++) {
 		wil_dbg_misc(wil, "SSID[%d]", i);
-		print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
-				     request->ssids[i].ssid,
-				     request->ssids[i].ssid_len);
+		wil_hex_dump_misc("SSID ", DUMP_PREFIX_OFFSET, 16, 1,
+				  request->ssids[i].ssid,
+				  request->ssids[i].ssid_len, true);
 	}
 
 	if (request->n_ssids)
@@ -538,8 +539,8 @@
 	}
 
 	if (request->ie_len)
-		print_hex_dump_bytes("Scan IE ", DUMP_PREFIX_OFFSET,
-				     request->ie, request->ie_len);
+		wil_hex_dump_misc("Scan IE ", DUMP_PREFIX_OFFSET, 16, 1,
+				  request->ie, request->ie_len, true);
 	else
 		wil_dbg_misc(wil, "Scan has no IE's\n");
 
@@ -763,6 +764,8 @@
 	rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn));
 	if (rc == 0) {
 		netif_carrier_on(ndev);
+		wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
+		wil->bss = bss;
 		/* Connect can take lots of time */
 		mod_timer(&wil->connect_timer,
 			  jiffies + msecs_to_jiffies(2000));
@@ -791,6 +794,7 @@
 		return 0;
 	}
 
+	wil->locally_generated_disc = true;
 	rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
 		      WMI_DISCONNECT_EVENTID, NULL, 0,
 		      WIL6210_DISCONNECT_TO_MS);
@@ -844,7 +848,8 @@
 	 */
 
 	wil_dbg_misc(wil, "mgmt_tx\n");
-	print_hex_dump_bytes("mgmt tx frame ", DUMP_PREFIX_OFFSET, buf, len);
+	wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf,
+			  len, true);
 
 	cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
 	if (!cmd) {
@@ -1177,18 +1182,18 @@
 
 static void wil_print_bcon_data(struct cfg80211_beacon_data *b)
 {
-	print_hex_dump_bytes("head     ", DUMP_PREFIX_OFFSET,
-			     b->head, b->head_len);
-	print_hex_dump_bytes("tail     ", DUMP_PREFIX_OFFSET,
-			     b->tail, b->tail_len);
-	print_hex_dump_bytes("BCON IE  ", DUMP_PREFIX_OFFSET,
-			     b->beacon_ies, b->beacon_ies_len);
-	print_hex_dump_bytes("PROBE    ", DUMP_PREFIX_OFFSET,
-			     b->probe_resp, b->probe_resp_len);
-	print_hex_dump_bytes("PROBE IE ", DUMP_PREFIX_OFFSET,
-			     b->proberesp_ies, b->proberesp_ies_len);
-	print_hex_dump_bytes("ASSOC IE ", DUMP_PREFIX_OFFSET,
-			     b->assocresp_ies, b->assocresp_ies_len);
+	wil_hex_dump_misc("head     ", DUMP_PREFIX_OFFSET, 16, 1,
+			  b->head, b->head_len, true);
+	wil_hex_dump_misc("tail     ", DUMP_PREFIX_OFFSET, 16, 1,
+			  b->tail, b->tail_len, true);
+	wil_hex_dump_misc("BCON IE  ", DUMP_PREFIX_OFFSET, 16, 1,
+			  b->beacon_ies, b->beacon_ies_len, true);
+	wil_hex_dump_misc("PROBE    ", DUMP_PREFIX_OFFSET, 16, 1,
+			  b->probe_resp, b->probe_resp_len, true);
+	wil_hex_dump_misc("PROBE IE ", DUMP_PREFIX_OFFSET, 16, 1,
+			  b->proberesp_ies, b->proberesp_ies_len, true);
+	wil_hex_dump_misc("ASSOC IE ", DUMP_PREFIX_OFFSET, 16, 1,
+			  b->assocresp_ies, b->assocresp_ies_len, true);
 }
 
 /* internal functions for device reset and starting AP */
@@ -1282,6 +1287,7 @@
 	wil->pbss = pbss;
 
 	netif_carrier_on(ndev);
+	wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
 
 	rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid, is_go);
 	if (rc)
@@ -1297,6 +1303,7 @@
 	wmi_pcp_stop(wil);
 err_pcp_start:
 	netif_carrier_off(ndev);
+	wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
 out:
 	mutex_unlock(&wil->mutex);
 	return rc;
@@ -1382,8 +1389,8 @@
 	wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval,
 		     info->dtim_period);
 	wil_dbg_misc(wil, "PBSS %d\n", info->pbss);
-	print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
-			     info->ssid, info->ssid_len);
+	wil_hex_dump_misc("SSID ", DUMP_PREFIX_OFFSET, 16, 1,
+			  info->ssid, info->ssid_len, true);
 	wil_print_bcon_data(bcon);
 	wil_print_crypto(wil, crypto);
 
@@ -1403,6 +1410,7 @@
 	wil_dbg_misc(wil, "stop_ap\n");
 
 	netif_carrier_off(ndev);
+	wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
 	wil_set_recovery_state(wil, fw_recovery_idle);
 
 	mutex_lock(&wil->mutex);
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 3e8cdf1..5648ebb 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -524,9 +524,8 @@
 	if (!buf)
 		return -ENOMEM;
 
-	wil_memcpy_fromio_halp_vote(wil_blob->wil, buf,
-				    (const volatile void __iomem *)
-				    wil_blob->blob.data + pos, count);
+	wil_memcpy_fromio_32(buf, (const void __iomem *)
+			     wil_blob->blob.data + pos, count);
 
 	ret = copy_to_user(user_buf, buf, count);
 	kfree(buf);
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 2c48419..36959a3 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -30,8 +30,8 @@
 module_param(debug_fw, bool, 0444);
 MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug");
 
-static bool oob_mode;
-module_param(oob_mode, bool, 0444);
+static u8 oob_mode;
+module_param(oob_mode, byte, 0444);
 MODULE_PARM_DESC(oob_mode,
 		 " enable out of the box (OOB) mode in FW, for diagnostics and certification");
 
@@ -135,14 +135,6 @@
 		*d++ = __raw_readl(s++);
 }
 
-void wil_memcpy_fromio_halp_vote(struct wil6210_priv *wil, void *dst,
-				 const volatile void __iomem *src, size_t count)
-{
-	wil_halp_vote(wil);
-	wil_memcpy_fromio_32(dst, src, count);
-	wil_halp_unvote(wil);
-}
-
 void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
 			size_t count)
 {
@@ -153,15 +145,6 @@
 		__raw_writel(*s++, d++);
 }
 
-void wil_memcpy_toio_halp_vote(struct wil6210_priv *wil,
-			       volatile void __iomem *dst,
-			       const void *src, size_t count)
-{
-	wil_halp_vote(wil);
-	wil_memcpy_toio_32(dst, src, count);
-	wil_halp_unvote(wil);
-}
-
 static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
 			       u16 reason_code, bool from_event)
 __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
@@ -274,15 +257,20 @@
 		wil_bcast_fini(wil);
 		wil_update_net_queues_bh(wil, NULL, true);
 		netif_carrier_off(ndev);
+		wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
 
 		if (test_bit(wil_status_fwconnected, wil->status)) {
 			clear_bit(wil_status_fwconnected, wil->status);
 			cfg80211_disconnected(ndev, reason_code,
-					      NULL, 0, false, GFP_KERNEL);
+					      NULL, 0,
+					      wil->locally_generated_disc,
+					      GFP_KERNEL);
+			wil->locally_generated_disc = false;
 		} else if (test_bit(wil_status_fwconnecting, wil->status)) {
 			cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
 						WLAN_STATUS_UNSPECIFIED_FAILURE,
 						GFP_KERNEL);
+			wil->bss = NULL;
 		}
 		clear_bit(wil_status_fwconnecting, wil->status);
 		break;
@@ -304,10 +292,34 @@
 {
 	struct wil6210_priv *wil = container_of(work,
 			struct wil6210_priv, disconnect_worker);
+	struct net_device *ndev = wil_to_ndev(wil);
+	int rc;
+	struct {
+		struct wmi_cmd_hdr wmi;
+		struct wmi_disconnect_event evt;
+	} __packed reply;
 
-	mutex_lock(&wil->mutex);
-	_wil6210_disconnect(wil, NULL, WLAN_REASON_UNSPECIFIED, false);
-	mutex_unlock(&wil->mutex);
+	if (test_bit(wil_status_fwconnected, wil->status))
+		/* connect succeeded after all */
+		return;
+
+	if (!test_bit(wil_status_fwconnecting, wil->status))
+		/* already disconnected */
+		return;
+
+	rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
+		      WMI_DISCONNECT_EVENTID, &reply, sizeof(reply),
+		      WIL6210_DISCONNECT_TO_MS);
+	if (rc) {
+		wil_err(wil, "disconnect error %d\n", rc);
+		return;
+	}
+
+	wil_update_net_queues_bh(wil, NULL, true);
+	netif_carrier_off(ndev);
+	cfg80211_connect_result(ndev, NULL, NULL, 0, NULL, 0,
+				WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL);
+	clear_bit(wil_status_fwconnecting, wil->status);
 }
 
 static void wil_connect_timer_fn(ulong x)
@@ -557,6 +569,12 @@
 	return -EAGAIN;
 }
 
+void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
+{
+	if (wil->platform_ops.bus_request)
+		wil->platform_ops.bus_request(wil->platform_handle, kbps);
+}
+
 /**
  * wil6210_disconnect - disconnect one connection
  * @wil: driver context
@@ -610,13 +628,25 @@
 	wil_w(wil, RGF_USER_USER_CPU_0, 1);
 }
 
-static void wil_set_oob_mode(struct wil6210_priv *wil, bool enable)
+static void wil_set_oob_mode(struct wil6210_priv *wil, u8 mode)
 {
-	wil_info(wil, "enable=%d\n", enable);
-	if (enable)
+	wil_info(wil, "oob_mode to %d\n", mode);
+	switch (mode) {
+	case 0:
+		wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE |
+		      BIT_USER_OOB_R2_MODE);
+		break;
+	case 1:
+		wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_R2_MODE);
 		wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE);
-	else
+		break;
+	case 2:
 		wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE);
+		wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_R2_MODE);
+		break;
+	default:
+		wil_err(wil, "invalid oob_mode: %d\n", mode);
+	}
 }
 
 static int wil_target_reset(struct wil6210_priv *wil)
@@ -1073,9 +1103,7 @@
 	napi_enable(&wil->napi_tx);
 	set_bit(wil_status_napi_en, wil->status);
 
-	if (wil->platform_ops.bus_request)
-		wil->platform_ops.bus_request(wil->platform_handle,
-					      WIL_MAX_BUS_REQUEST_KBPS);
+	wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
 
 	return 0;
 }
@@ -1099,8 +1127,7 @@
 
 	set_bit(wil_status_resetting, wil->status);
 
-	if (wil->platform_ops.bus_request)
-		wil->platform_ops.bus_request(wil->platform_handle, 0);
+	wil6210_bus_request(wil, 0);
 
 	wil_disable_irq(wil);
 	if (test_and_clear_bit(wil_status_napi_en, wil->status)) {
@@ -1163,6 +1190,7 @@
 		    wil->halp.ref_cnt);
 
 	if (++wil->halp.ref_cnt == 1) {
+		reinit_completion(&wil->halp.comp);
 		wil6210_set_halp(wil);
 		rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies);
 		if (!rc) {
diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c
index 7260bef..2ae4fe8 100644
--- a/drivers/net/wireless/ath/wil6210/pm.c
+++ b/drivers/net/wireless/ath/wil6210/pm.c
@@ -71,6 +71,11 @@
 
 	wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
 
+	if (test_bit(wil_status_suspended, wil->status)) {
+		wil_dbg_pm(wil, "trying to suspend while suspended\n");
+		return 0;
+	}
+
 	/* if netif up, hardware is alive, shut it down */
 	if (ndev->flags & IFF_UP) {
 		rc = wil_down(wil);
@@ -86,10 +91,14 @@
 
 	if (wil->platform_ops.suspend) {
 		rc = wil->platform_ops.suspend(wil->platform_handle);
-		if (rc)
+		if (rc) {
 			wil_enable_irq(wil);
+			goto out;
+		}
 	}
 
+	set_bit(wil_status_suspended, wil->status);
+
 out:
 	wil_dbg_pm(wil, "suspend: %s => %d\n",
 		   is_runtime ? "runtime" : "system", rc);
@@ -117,10 +126,13 @@
 
 	/* if netif up, bring hardware up
 	 * During open(), IFF_UP set after actual device method
-	 * invocation. This prevent recursive call to wil_up()
+	 * invocation. This prevent recursive call to wil_up().
+	 * wil_status_suspended will be cleared in wil_reset
 	 */
 	if (ndev->flags & IFF_UP)
 		rc = wil_up(wil);
+	else
+		clear_bit(wil_status_suspended, wil->status);
 
 out:
 	wil_dbg_pm(wil, "resume: %s => %d\n",
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 4bccef3..734449d 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -41,6 +41,7 @@
 #define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw" /* code Sparrow D0 */
 #define WIL_BOARD_FILE_NAME "wil6210.brd" /* board & radio parameters */
 
+#define WIL_DEFAULT_BUS_REQUEST_KBPS 128000 /* ~1Gbps */
 #define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */
 
 /**
@@ -140,6 +141,7 @@
 #define RGF_USER_USAGE_1		(0x880004)
 #define RGF_USER_USAGE_6		(0x880018)
 	#define BIT_USER_OOB_MODE		BIT(31)
+	#define BIT_USER_OOB_R2_MODE		BIT(30)
 #define RGF_USER_USAGE_8		(0x880020)
 	#define BIT_USER_PREVENT_DEEP_SLEEP	BIT(0)
 	#define BIT_USER_SUPPORT_T_POWER_ON_0	BIT(1)
@@ -413,6 +415,7 @@
 	wil_status_irqen, /* FIXME: interrupts enabled - for debug */
 	wil_status_napi_en, /* NAPI enabled protected by wil->mutex */
 	wil_status_resetting, /* reset in progress */
+	wil_status_suspended, /* suspend completed, device is suspended */
 	wil_status_last /* keep last */
 };
 
@@ -616,6 +619,8 @@
 	u16 channel; /* relevant in AP mode */
 	int sinfo_gen;
 	u32 ap_isolate; /* no intra-BSS communication */
+	struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */
+	int locally_generated_disc; /* relevant in STA mode */
 	/* interrupt moderation */
 	u32 tx_max_burst_duration;
 	u32 tx_interframe_timeout;
@@ -771,6 +776,12 @@
 			 print_hex_dump_debug("DBG[ WMI]" prefix_str,\
 					prefix_type, rowsize,	\
 					groupsize, buf, len, ascii)
+
+#define wil_hex_dump_misc(prefix_str, prefix_type, rowsize,	\
+			  groupsize, buf, len, ascii)		\
+			  print_hex_dump_debug("DBG[MISC]" prefix_str,\
+					prefix_type, rowsize,	\
+					groupsize, buf, len, ascii)
 #else /* defined(CONFIG_DYNAMIC_DEBUG) */
 static inline
 void wil_hex_dump_txrx(const char *prefix_str, int prefix_type, int rowsize,
@@ -783,18 +794,18 @@
 		      int groupsize, const void *buf, size_t len, bool ascii)
 {
 }
+
+static inline
+void wil_hex_dump_misc(const char *prefix_str, int prefix_type, int rowsize,
+		       int groupsize, const void *buf, size_t len, bool ascii)
+{
+}
 #endif /* defined(CONFIG_DYNAMIC_DEBUG) */
 
 void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
 			  size_t count);
 void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
 			size_t count);
-void wil_memcpy_fromio_halp_vote(struct wil6210_priv *wil, void *dst,
-				 const volatile void __iomem *src,
-				 size_t count);
-void wil_memcpy_toio_halp_vote(struct wil6210_priv *wil,
-			       volatile void __iomem *dst,
-			       const void *src, size_t count);
 
 void *wil_if_alloc(struct device *dev);
 void wil_if_free(struct wil6210_priv *wil);
@@ -910,7 +921,7 @@
 		 u8 type);
 int wmi_abort_scan(struct wil6210_priv *wil);
 void wil_abort_scan(struct wil6210_priv *wil, bool sync);
-
+void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps);
 void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
 			u16 reason_code, bool from_event);
 void wil_probe_client_flush(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 0ede7f7..31d6ab9 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -566,6 +566,7 @@
 	    (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
 		if (rc) {
 			netif_carrier_off(ndev);
+			wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
 			wil_err(wil, "cfg80211_connect_result with failure\n");
 			cfg80211_connect_result(ndev, evt->bssid, NULL, 0,
 						NULL, 0,
@@ -573,12 +574,16 @@
 						GFP_KERNEL);
 			goto out;
 		} else {
-			cfg80211_connect_result(ndev, evt->bssid,
-						assoc_req_ie, assoc_req_ielen,
-						assoc_resp_ie, assoc_resp_ielen,
-						WLAN_STATUS_SUCCESS,
-						GFP_KERNEL);
+			struct wiphy *wiphy = wil_to_wiphy(wil);
+
+			cfg80211_ref_bss(wiphy, wil->bss);
+			cfg80211_connect_bss(ndev, evt->bssid, wil->bss,
+					     assoc_req_ie, assoc_req_ielen,
+					     assoc_resp_ie, assoc_resp_ielen,
+					     WLAN_STATUS_SUCCESS, GFP_KERNEL,
+					     NL80211_TIMEOUT_UNSPECIFIED);
 		}
+		wil->bss = NULL;
 	} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
 		   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
 		if (rc) {
@@ -1524,6 +1529,7 @@
 
 	wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason);
 
+	wil->locally_generated_disc = true;
 	if (del_sta) {
 		ether_addr_copy(del_sta_cmd.dst_mac, mac);
 		rc = wmi_call(wil, WMI_DEL_STA_CMDID, &del_sta_cmd,
@@ -1765,14 +1771,19 @@
 
 void wmi_event_flush(struct wil6210_priv *wil)
 {
+	ulong flags;
 	struct pending_wmi_event *evt, *t;
 
 	wil_dbg_wmi(wil, "event_flush\n");
 
+	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
+
 	list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
 		list_del(&evt->list);
 		kfree(evt);
 	}
+
+	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
 }
 
 static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 6555eb7..6ae8964 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -120,6 +120,20 @@
 
 	  If unsure, say N.
 
+config PCI_MSM
+	bool "MSM PCIe Controller driver"
+	depends on ARCH_QCOM && PCI
+	select PCI_DOMAINS
+	select PCI_DOMAINS_GENERIC
+	select PCI_MSI
+	help
+	  Enables the PCIe functionality by configuring PCIe core on
+	  MSM chipset and by enabling the ARM PCI framework extension.
+	  The PCIe core is essential for communication between the host
+	  and an endpoint.
+
+	  If unsure, say N.
+
 config PCI_LABEL
 	def_bool y if (DMI || ACPI)
 	select NLS
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 16c9096..a0fa943 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -27,11 +27,11 @@
 #include <linux/iommu.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
-#include <linux/regulator/rpm-smd-regulator.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/of_gpio.h>
-#include <linux/clk/msm-clk.h>
+#include <linux/clk/qcom.h>
 #include <linux/reset.h>
 #include <linux/msm-bus.h>
 #include <linux/msm-bus-board.h>
@@ -48,170 +48,27 @@
 #include <linux/ipc_logging.h>
 #include <linux/msm_pcie.h>
 
-#ifdef CONFIG_ARCH_MDMCALIFORNIUM
 #define PCIE_VENDOR_ID_RCP		0x17cb
-#define PCIE_DEVICE_ID_RCP		0x0302
-
-#define PCIE20_L1SUB_CONTROL1		0x158
-#define PCIE20_PARF_DBI_BASE_ADDR	0x350
-#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE	0x358
-
-#define TX_BASE 0x200
-#define RX_BASE 0x400
-#define PCS_BASE 0x800
-#define PCS_MISC_BASE 0x600
-
-#elif defined(CONFIG_ARCH_MSM8998)
-#define PCIE_VENDOR_ID_RCP		0x17cb
-#define PCIE_DEVICE_ID_RCP		0x0105
+#define PCIE_DEVICE_ID_RCP		0x0106
 
 #define PCIE20_L1SUB_CONTROL1		0x1E4
 #define PCIE20_PARF_DBI_BASE_ADDR       0x350
 #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x358
 
-#define TX_BASE 0
-#define RX_BASE 0
 #define PCS_BASE 0x800
-#define PCS_MISC_BASE 0
 
-#else
-#define PCIE_VENDOR_ID_RCP		0x17cb
-#define PCIE_DEVICE_ID_RCP		0x0104
-
-#define PCIE20_L1SUB_CONTROL1		0x158
-#define PCIE20_PARF_DBI_BASE_ADDR	0x168
-#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE	0x16C
-
-#define TX_BASE 0x1000
-#define RX_BASE 0x1200
-#define PCS_BASE 0x1400
-#define PCS_MISC_BASE 0
-#endif
-
-#define TX(n, m) (TX_BASE + n * m * 0x1000)
-#define RX(n, m) (RX_BASE + n * m * 0x1000)
 #define PCS_PORT(n, m) (PCS_BASE + n * m * 0x1000)
-#define PCS_MISC_PORT(n, m) (PCS_MISC_BASE + n * m * 0x1000)
-
-#define QSERDES_COM_BG_TIMER			0x00C
-#define QSERDES_COM_SSC_EN_CENTER		0x010
-#define QSERDES_COM_SSC_ADJ_PER1		0x014
-#define QSERDES_COM_SSC_ADJ_PER2		0x018
-#define QSERDES_COM_SSC_PER1			0x01C
-#define QSERDES_COM_SSC_PER2			0x020
-#define QSERDES_COM_SSC_STEP_SIZE1		0x024
-#define QSERDES_COM_SSC_STEP_SIZE2		0x028
-#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN		0x034
-#define QSERDES_COM_CLK_ENABLE1			0x038
-#define QSERDES_COM_SYS_CLK_CTRL		0x03C
-#define QSERDES_COM_SYSCLK_BUF_ENABLE		0x040
-#define QSERDES_COM_PLL_IVCO			0x048
-#define QSERDES_COM_LOCK_CMP1_MODE0		0x04C
-#define QSERDES_COM_LOCK_CMP2_MODE0		0x050
-#define QSERDES_COM_LOCK_CMP3_MODE0		0x054
-#define QSERDES_COM_BG_TRIM			0x070
-#define QSERDES_COM_CLK_EP_DIV			0x074
-#define QSERDES_COM_CP_CTRL_MODE0		0x078
-#define QSERDES_COM_PLL_RCTRL_MODE0		0x084
-#define QSERDES_COM_PLL_CCTRL_MODE0		0x090
-#define QSERDES_COM_SYSCLK_EN_SEL		0x0AC
-#define QSERDES_COM_RESETSM_CNTRL		0x0B4
-#define QSERDES_COM_RESTRIM_CTRL		0x0BC
-#define QSERDES_COM_RESCODE_DIV_NUM		0x0C4
-#define QSERDES_COM_LOCK_CMP_EN			0x0C8
-#define QSERDES_COM_DEC_START_MODE0		0x0D0
-#define QSERDES_COM_DIV_FRAC_START1_MODE0	0x0DC
-#define QSERDES_COM_DIV_FRAC_START2_MODE0	0x0E0
-#define QSERDES_COM_DIV_FRAC_START3_MODE0	0x0E4
-#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0	0x108
-#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0	0x10C
-#define QSERDES_COM_VCO_TUNE_CTRL		0x124
-#define QSERDES_COM_VCO_TUNE_MAP		0x128
-#define QSERDES_COM_VCO_TUNE1_MODE0		0x12C
-#define QSERDES_COM_VCO_TUNE2_MODE0		0x130
-#define QSERDES_COM_VCO_TUNE_TIMER1		0x144
-#define QSERDES_COM_VCO_TUNE_TIMER2		0x148
-#define QSERDES_COM_BG_CTRL			0x170
-#define QSERDES_COM_CLK_SELECT			0x174
-#define QSERDES_COM_HSCLK_SEL			0x178
-#define QSERDES_COM_CORECLK_DIV			0x184
-#define QSERDES_COM_CORE_CLK_EN			0x18C
-#define QSERDES_COM_C_READY_STATUS		0x190
-#define QSERDES_COM_CMN_CONFIG			0x194
-#define QSERDES_COM_SVS_MODE_CLK_SEL		0x19C
-#define QSERDES_COM_DEBUG_BUS0			0x1A0
-#define QSERDES_COM_DEBUG_BUS1			0x1A4
-#define QSERDES_COM_DEBUG_BUS2			0x1A8
-#define QSERDES_COM_DEBUG_BUS3			0x1AC
-#define QSERDES_COM_DEBUG_BUS_SEL		0x1B0
-
-#define QSERDES_TX_N_RES_CODE_LANE_OFFSET(n, m)		(TX(n, m) + 0x4C)
-#define QSERDES_TX_N_DEBUG_BUS_SEL(n, m)		(TX(n, m) + 0x64)
-#define QSERDES_TX_N_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN(n, m) (TX(n, m) + 0x68)
-#define QSERDES_TX_N_LANE_MODE(n, m)			(TX(n, m) + 0x94)
-#define QSERDES_TX_N_RCV_DETECT_LVL_2(n, m)		(TX(n, m) + 0xAC)
-
-#define QSERDES_RX_N_UCDR_SO_GAIN_HALF(n, m)		(RX(n, m) + 0x010)
-#define QSERDES_RX_N_UCDR_SO_GAIN(n, m)			(RX(n, m) + 0x01C)
-#define QSERDES_RX_N_UCDR_SO_SATURATION_AND_ENABLE(n, m) (RX(n, m) + 0x048)
-#define QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL2(n, m)	(RX(n, m) + 0x0D8)
-#define QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL3(n, m)	(RX(n, m) + 0x0DC)
-#define QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL4(n, m)	(RX(n, m) + 0x0E0)
-#define QSERDES_RX_N_SIGDET_ENABLES(n, m)		(RX(n, m) + 0x110)
-#define QSERDES_RX_N_SIGDET_DEGLITCH_CNTRL(n, m)	(RX(n, m) + 0x11C)
-#define QSERDES_RX_N_SIGDET_LVL(n, m)			(RX(n, m) + 0x118)
-#define QSERDES_RX_N_RX_BAND(n, m)			(RX(n, m) + 0x120)
-
-#define PCIE_MISC_N_DEBUG_BUS_BYTE0_INDEX(n, m)	(PCS_MISC_PORT(n, m) + 0x00)
-#define PCIE_MISC_N_DEBUG_BUS_BYTE1_INDEX(n, m)	(PCS_MISC_PORT(n, m) + 0x04)
-#define PCIE_MISC_N_DEBUG_BUS_BYTE2_INDEX(n, m)	(PCS_MISC_PORT(n, m) + 0x08)
-#define PCIE_MISC_N_DEBUG_BUS_BYTE3_INDEX(n, m)	(PCS_MISC_PORT(n, m) + 0x0C)
-#define PCIE_MISC_N_DEBUG_BUS_0_STATUS(n, m)	(PCS_MISC_PORT(n, m) + 0x14)
-#define PCIE_MISC_N_DEBUG_BUS_1_STATUS(n, m)	(PCS_MISC_PORT(n, m) + 0x18)
-#define PCIE_MISC_N_DEBUG_BUS_2_STATUS(n, m)	(PCS_MISC_PORT(n, m) + 0x1C)
-#define PCIE_MISC_N_DEBUG_BUS_3_STATUS(n, m)	(PCS_MISC_PORT(n, m) + 0x20)
 
 #define PCIE_N_SW_RESET(n, m)			(PCS_PORT(n, m) + 0x00)
 #define PCIE_N_POWER_DOWN_CONTROL(n, m)		(PCS_PORT(n, m) + 0x04)
-#define PCIE_N_START_CONTROL(n, m)		(PCS_PORT(n, m) + 0x08)
-#define PCIE_N_TXDEEMPH_M6DB_V0(n, m)		(PCS_PORT(n, m) + 0x24)
-#define PCIE_N_TXDEEMPH_M3P5DB_V0(n, m)		(PCS_PORT(n, m) + 0x28)
-#define PCIE_N_ENDPOINT_REFCLK_DRIVE(n, m)	(PCS_PORT(n, m) + 0x54)
-#define PCIE_N_RX_IDLE_DTCT_CNTRL(n, m)		(PCS_PORT(n, m) + 0x58)
-#define PCIE_N_POWER_STATE_CONFIG1(n, m)	(PCS_PORT(n, m) + 0x60)
-#define PCIE_N_POWER_STATE_CONFIG4(n, m)	(PCS_PORT(n, m) + 0x6C)
-#define PCIE_N_PWRUP_RESET_DLY_TIME_AUXCLK(n, m)	(PCS_PORT(n, m) + 0xA0)
-#define PCIE_N_LP_WAKEUP_DLY_TIME_AUXCLK(n, m)	(PCS_PORT(n, m) + 0xA4)
-#define PCIE_N_PLL_LOCK_CHK_DLY_TIME(n, m)	(PCS_PORT(n, m) + 0xA8)
-#define PCIE_N_TEST_CONTROL4(n, m)		(PCS_PORT(n, m) + 0x11C)
-#define PCIE_N_TEST_CONTROL5(n, m)		(PCS_PORT(n, m) + 0x120)
-#define PCIE_N_TEST_CONTROL6(n, m)		(PCS_PORT(n, m) + 0x124)
-#define PCIE_N_TEST_CONTROL7(n, m)		(PCS_PORT(n, m) + 0x128)
 #define PCIE_N_PCS_STATUS(n, m)			(PCS_PORT(n, m) + 0x174)
-#define PCIE_N_DEBUG_BUS_0_STATUS(n, m)		(PCS_PORT(n, m) + 0x198)
-#define PCIE_N_DEBUG_BUS_1_STATUS(n, m)		(PCS_PORT(n, m) + 0x19C)
-#define PCIE_N_DEBUG_BUS_2_STATUS(n, m)		(PCS_PORT(n, m) + 0x1A0)
-#define PCIE_N_DEBUG_BUS_3_STATUS(n, m)		(PCS_PORT(n, m) + 0x1A4)
-#define PCIE_N_LP_WAKEUP_DLY_TIME_AUXCLK_MSB(n, m)	(PCS_PORT(n, m) + 0x1A8)
-#define PCIE_N_OSC_DTCT_ACTIONS(n, m)			(PCS_PORT(n, m) + 0x1AC)
-#define PCIE_N_SIGDET_CNTRL(n, m)			(PCS_PORT(n, m) + 0x1B0)
-#define PCIE_N_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB(n, m)	(PCS_PORT(n, m) + 0x1DC)
-#define PCIE_N_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB(n, m)	(PCS_PORT(n, m) + 0x1E0)
 
 #define PCIE_COM_SW_RESET		0x400
 #define PCIE_COM_POWER_DOWN_CONTROL	0x404
-#define PCIE_COM_START_CONTROL		0x408
-#define PCIE_COM_DEBUG_BUS_BYTE0_INDEX	0x438
-#define PCIE_COM_DEBUG_BUS_BYTE1_INDEX	0x43C
-#define PCIE_COM_DEBUG_BUS_BYTE2_INDEX	0x440
-#define PCIE_COM_DEBUG_BUS_BYTE3_INDEX	0x444
 #define PCIE_COM_PCS_READY_STATUS	0x448
-#define PCIE_COM_DEBUG_BUS_0_STATUS	0x45C
-#define PCIE_COM_DEBUG_BUS_1_STATUS	0x460
-#define PCIE_COM_DEBUG_BUS_2_STATUS	0x464
-#define PCIE_COM_DEBUG_BUS_3_STATUS	0x468
 
 #define PCIE20_PARF_SYS_CTRL	     0x00
+#define PCIE20_PARF_PM_CTRL		0x20
 #define PCIE20_PARF_PM_STTS		0x24
 #define PCIE20_PARF_PCS_DEEMPH	   0x34
 #define PCIE20_PARF_PCS_SWING	    0x38
@@ -228,6 +85,7 @@
 #define PCIE20_PARF_SID_OFFSET		0x234
 #define PCIE20_PARF_BDF_TRANSLATE_CFG	0x24C
 #define PCIE20_PARF_BDF_TRANSLATE_N	0x250
+#define PCIE20_PARF_DEVICE_TYPE		0x1000
 
 #define PCIE20_ELBI_VERSION		0x00
 #define PCIE20_ELBI_SYS_CTRL	     0x04
@@ -300,7 +158,7 @@
 #define MAX_PROP_SIZE 32
 #define MAX_RC_NAME_LEN 15
 #define MSM_PCIE_MAX_VREG 4
-#define MSM_PCIE_MAX_CLK 9
+#define MSM_PCIE_MAX_CLK 12
 #define MSM_PCIE_MAX_PIPE_CLK 1
 #define MAX_RC_NUM 3
 #define MAX_DEVICE_NUM 20
@@ -314,7 +172,7 @@
 #define PCIE_CLEAR				0xDEADBEEF
 #define PCIE_LINK_DOWN				0xFFFFFFFF
 
-#define MSM_PCIE_MAX_RESET 4
+#define MSM_PCIE_MAX_RESET 5
 #define MSM_PCIE_MAX_PIPE_RESET 1
 
 #define MSM_PCIE_MSI_PHY 0xa0000000
@@ -629,7 +487,6 @@
 	uint32_t			wr_halt_size;
 	uint32_t			cpl_timeout;
 	uint32_t			current_bdf;
-	short				current_short_bdf;
 	uint32_t			perst_delay_us_min;
 	uint32_t			perst_delay_us_max;
 	uint32_t			tlp_rd_size;
@@ -734,18 +591,21 @@
 static struct msm_pcie_reset_info_t
 msm_pcie_reset_info[MAX_RC_NUM][MSM_PCIE_MAX_RESET] = {
 	{
+		{NULL, "pcie_0_core_reset", false},
 		{NULL, "pcie_phy_reset", false},
 		{NULL, "pcie_phy_com_reset", false},
 		{NULL, "pcie_phy_nocsr_com_phy_reset", false},
 		{NULL, "pcie_0_phy_reset", false}
 	},
 	{
+		{NULL, "pcie_1_core_reset", false},
 		{NULL, "pcie_phy_reset", false},
 		{NULL, "pcie_phy_com_reset", false},
 		{NULL, "pcie_phy_nocsr_com_phy_reset", false},
 		{NULL, "pcie_1_phy_reset", false}
 	},
 	{
+		{NULL, "pcie_2_core_reset", false},
 		{NULL, "pcie_phy_reset", false},
 		{NULL, "pcie_phy_com_reset", false},
 		{NULL, "pcie_phy_nocsr_com_phy_reset", false},
@@ -778,6 +638,9 @@
 	{NULL, "pcie_0_slv_axi_clk", 0, true, true},
 	{NULL, "pcie_0_ldo", 0, false, true},
 	{NULL, "pcie_0_smmu_clk", 0, false, false},
+	{NULL, "pcie_0_slv_q2a_axi_clk", 0, false, false},
+	{NULL, "pcie_phy_refgen_clk", 0, false, false},
+	{NULL, "pcie_tbu_clk", 0, false, false},
 	{NULL, "pcie_phy_cfg_ahb_clk", 0, false, false},
 	{NULL, "pcie_phy_aux_clk", 0, false, false}
 	},
@@ -789,6 +652,9 @@
 	{NULL, "pcie_1_slv_axi_clk", 0, true,  true},
 	{NULL, "pcie_1_ldo", 0, false, true},
 	{NULL, "pcie_1_smmu_clk", 0, false, false},
+	{NULL, "pcie_1_slv_q2a_axi_clk", 0, false, false},
+	{NULL, "pcie_phy_refgen_clk", 0, false, false},
+	{NULL, "pcie_tbu_clk", 0, false, false},
 	{NULL, "pcie_phy_cfg_ahb_clk", 0, false, false},
 	{NULL, "pcie_phy_aux_clk", 0, false, false}
 	},
@@ -800,6 +666,9 @@
 	{NULL, "pcie_2_slv_axi_clk", 0, true, true},
 	{NULL, "pcie_2_ldo", 0, false, true},
 	{NULL, "pcie_2_smmu_clk", 0, false, false},
+	{NULL, "pcie_2_slv_q2a_axi_clk", 0, false, false},
+	{NULL, "pcie_phy_refgen_clk", 0, false, false},
+	{NULL, "pcie_tbu_clk", 0, false, false},
 	{NULL, "pcie_phy_cfg_ahb_clk", 0, false, false},
 	{NULL, "pcie_phy_aux_clk", 0, false, false}
 	}
@@ -860,6 +729,8 @@
 	{"msi_28", 0}, {"msi_29", 0}, {"msi_30", 0}, {"msi_31", 0}
 };
 
+static int msm_pcie_config_device(struct pci_dev *dev, void *pdev);
+
 #ifdef CONFIG_ARM
 #define PCIE_BUS_PRIV_DATA(bus) \
 	(((struct pci_sys_data *)bus->sysdata)->private_data)
@@ -938,393 +809,9 @@
 			dev->rc_idx, info->name);
 }
 
-#if defined(CONFIG_ARCH_FSM9010)
-#define PCIE20_PARF_PHY_STTS         0x3c
-#define PCIE2_PHY_RESET_CTRL         0x44
-#define PCIE20_PARF_PHY_REFCLK_CTRL2 0xa0
-#define PCIE20_PARF_PHY_REFCLK_CTRL3 0xa4
-#define PCIE20_PARF_PCS_SWING_CTRL1  0x88
-#define PCIE20_PARF_PCS_SWING_CTRL2  0x8c
-#define PCIE20_PARF_PCS_DEEMPH1      0x74
-#define PCIE20_PARF_PCS_DEEMPH2      0x78
-#define PCIE20_PARF_PCS_DEEMPH3      0x7c
-#define PCIE20_PARF_CONFIGBITS       0x84
-#define PCIE20_PARF_PHY_CTRL3        0x94
-#define PCIE20_PARF_PCS_CTRL         0x80
-
-#define TX_AMP_VAL                   127
-#define PHY_RX0_EQ_GEN1_VAL          0
-#define PHY_RX0_EQ_GEN2_VAL          4
-#define TX_DEEMPH_GEN1_VAL           24
-#define TX_DEEMPH_GEN2_3_5DB_VAL     24
-#define TX_DEEMPH_GEN2_6DB_VAL       34
-#define PHY_TX0_TERM_OFFST_VAL       0
-
-static inline void pcie_phy_dump(struct msm_pcie_dev_t *dev)
-{
-}
-
-static inline void pcie20_phy_reset(struct msm_pcie_dev_t *dev, uint32_t assert)
-{
-	msm_pcie_write_reg_field(dev->phy, PCIE2_PHY_RESET_CTRL,
-					 BIT(0), (assert) ? 1 : 0);
-}
-
-static void pcie_phy_init(struct msm_pcie_dev_t *dev)
-{
-	PCIE_DBG(dev, "RC%d: Initializing 28LP SNS phy - 100MHz\n",
-		dev->rc_idx);
-
-	/* De-assert Phy SW Reset */
-	pcie20_phy_reset(dev, 1);
-
-	/* Program SSP ENABLE */
-	if (readl_relaxed(dev->phy + PCIE20_PARF_PHY_REFCLK_CTRL2) & BIT(0))
-		msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PHY_REFCLK_CTRL2,
-								 BIT(0), 0);
-	if ((readl_relaxed(dev->phy + PCIE20_PARF_PHY_REFCLK_CTRL3) &
-								 BIT(0)) == 0)
-		msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PHY_REFCLK_CTRL3,
-								 BIT(0), 1);
-	/* Program Tx Amplitude */
-	if ((readl_relaxed(dev->phy + PCIE20_PARF_PCS_SWING_CTRL1) &
-		(BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
-				TX_AMP_VAL)
-		msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_SWING_CTRL1,
-			BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
-				TX_AMP_VAL);
-	if ((readl_relaxed(dev->phy + PCIE20_PARF_PCS_SWING_CTRL2) &
-		(BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
-				TX_AMP_VAL)
-		msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_SWING_CTRL2,
-			BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
-				TX_AMP_VAL);
-	/* Program De-Emphasis */
-	if ((readl_relaxed(dev->phy + PCIE20_PARF_PCS_DEEMPH1) &
-			(BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
-				TX_DEEMPH_GEN2_6DB_VAL)
-		msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_DEEMPH1,
-			BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
-				TX_DEEMPH_GEN2_6DB_VAL);
-
-	if ((readl_relaxed(dev->phy + PCIE20_PARF_PCS_DEEMPH2) &
-			(BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
-				TX_DEEMPH_GEN2_3_5DB_VAL)
-		msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_DEEMPH2,
-			BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
-				TX_DEEMPH_GEN2_3_5DB_VAL);
-
-	if ((readl_relaxed(dev->phy + PCIE20_PARF_PCS_DEEMPH3) &
-			(BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
-				TX_DEEMPH_GEN1_VAL)
-		msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_DEEMPH3,
-			BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
-				TX_DEEMPH_GEN1_VAL);
-
-	/* Program Rx_Eq */
-	if ((readl_relaxed(dev->phy + PCIE20_PARF_CONFIGBITS) &
-			(BIT(2)|BIT(1)|BIT(0))) != PHY_RX0_EQ_GEN1_VAL)
-		msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_CONFIGBITS,
-				 BIT(2)|BIT(1)|BIT(0), PHY_RX0_EQ_GEN1_VAL);
-
-	/* Program Tx0_term_offset */
-	if ((readl_relaxed(dev->phy + PCIE20_PARF_PHY_CTRL3) &
-			(BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0))) !=
-				PHY_TX0_TERM_OFFST_VAL)
-		msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PHY_CTRL3,
-			 BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
-				PHY_TX0_TERM_OFFST_VAL);
-
-	/* Program REF_CLK source */
-	msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PHY_REFCLK_CTRL2, BIT(1),
-		(dev->ext_ref_clk) ? 1 : 0);
-	/* disable Tx2Rx Loopback */
-	if (readl_relaxed(dev->phy + PCIE20_PARF_PCS_CTRL) & BIT(1))
-		msm_pcie_write_reg_field(dev->phy, PCIE20_PARF_PCS_CTRL,
-								 BIT(1), 0);
-	/* De-assert Phy SW Reset */
-	pcie20_phy_reset(dev, 0);
-}
-
-static bool pcie_phy_is_ready(struct msm_pcie_dev_t *dev)
-{
-
-	/* read PCIE20_PARF_PHY_STTS twice */
-	readl_relaxed(dev->phy + PCIE20_PARF_PHY_STTS);
-	if (readl_relaxed(dev->phy + PCIE20_PARF_PHY_STTS) & BIT(0))
-		return false;
-	else
-		return true;
-}
-#else
-static void pcie_phy_dump_test_cntrl(struct msm_pcie_dev_t *dev,
-					u32 cntrl4_val, u32 cntrl5_val,
-					u32 cntrl6_val, u32 cntrl7_val)
-{
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_TEST_CONTROL4(dev->rc_idx, dev->common_phy), cntrl4_val);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_TEST_CONTROL5(dev->rc_idx, dev->common_phy), cntrl5_val);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_TEST_CONTROL6(dev->rc_idx, dev->common_phy), cntrl6_val);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_TEST_CONTROL7(dev->rc_idx, dev->common_phy), cntrl7_val);
-
-	PCIE_DUMP(dev,
-		"PCIe: RC%d PCIE_N_TEST_CONTROL4: 0x%x\n", dev->rc_idx,
-		readl_relaxed(dev->phy +
-			PCIE_N_TEST_CONTROL4(dev->rc_idx,
-				dev->common_phy)));
-	PCIE_DUMP(dev,
-		"PCIe: RC%d PCIE_N_TEST_CONTROL5: 0x%x\n", dev->rc_idx,
-		readl_relaxed(dev->phy +
-			PCIE_N_TEST_CONTROL5(dev->rc_idx,
-				dev->common_phy)));
-	PCIE_DUMP(dev,
-		"PCIe: RC%d PCIE_N_TEST_CONTROL6: 0x%x\n", dev->rc_idx,
-		readl_relaxed(dev->phy +
-			PCIE_N_TEST_CONTROL6(dev->rc_idx,
-				dev->common_phy)));
-	PCIE_DUMP(dev,
-		"PCIe: RC%d PCIE_N_TEST_CONTROL7: 0x%x\n", dev->rc_idx,
-		readl_relaxed(dev->phy +
-			PCIE_N_TEST_CONTROL7(dev->rc_idx,
-				dev->common_phy)));
-	PCIE_DUMP(dev,
-		"PCIe: RC%d PCIE_N_DEBUG_BUS_0_STATUS: 0x%x\n", dev->rc_idx,
-		readl_relaxed(dev->phy +
-			PCIE_N_DEBUG_BUS_0_STATUS(dev->rc_idx,
-				dev->common_phy)));
-	PCIE_DUMP(dev,
-		"PCIe: RC%d PCIE_N_DEBUG_BUS_1_STATUS: 0x%x\n", dev->rc_idx,
-		readl_relaxed(dev->phy +
-			PCIE_N_DEBUG_BUS_1_STATUS(dev->rc_idx,
-				dev->common_phy)));
-	PCIE_DUMP(dev,
-		"PCIe: RC%d PCIE_N_DEBUG_BUS_2_STATUS: 0x%x\n", dev->rc_idx,
-		readl_relaxed(dev->phy +
-			PCIE_N_DEBUG_BUS_2_STATUS(dev->rc_idx,
-				dev->common_phy)));
-	PCIE_DUMP(dev,
-		"PCIe: RC%d PCIE_N_DEBUG_BUS_3_STATUS: 0x%x\n\n", dev->rc_idx,
-		readl_relaxed(dev->phy +
-			PCIE_N_DEBUG_BUS_3_STATUS(dev->rc_idx,
-				dev->common_phy)));
-}
-
 static void pcie_phy_dump(struct msm_pcie_dev_t *dev)
 {
 	int i, size;
-	u32 write_val;
-
-	if (dev->phy_ver >= 0x20) {
-		PCIE_DUMP(dev, "PCIe: RC%d PHY dump is not supported\n",
-			dev->rc_idx);
-		return;
-	}
-
-	PCIE_DUMP(dev, "PCIe: RC%d PHY testbus\n", dev->rc_idx);
-
-	pcie_phy_dump_test_cntrl(dev, 0x18, 0x19, 0x1A, 0x1B);
-	pcie_phy_dump_test_cntrl(dev, 0x1C, 0x1D, 0x1E, 0x1F);
-	pcie_phy_dump_test_cntrl(dev, 0x20, 0x21, 0x22, 0x23);
-
-	for (i = 0; i < 3; i++) {
-		write_val = 0x1 + i;
-		msm_pcie_write_reg(dev->phy,
-			QSERDES_TX_N_DEBUG_BUS_SEL(dev->rc_idx,
-				dev->common_phy), write_val);
-		PCIE_DUMP(dev,
-			"PCIe: RC%d QSERDES_TX_N_DEBUG_BUS_SEL: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy +
-				QSERDES_TX_N_DEBUG_BUS_SEL(dev->rc_idx,
-					dev->common_phy)));
-
-		pcie_phy_dump_test_cntrl(dev, 0x30, 0x31, 0x32, 0x33);
-	}
-
-	pcie_phy_dump_test_cntrl(dev, 0, 0, 0, 0);
-
-	if (dev->phy_ver >= 0x10 && dev->phy_ver < 0x20) {
-		pcie_phy_dump_test_cntrl(dev, 0x01, 0x02, 0x03, 0x0A);
-		pcie_phy_dump_test_cntrl(dev, 0x0E, 0x0F, 0x12, 0x13);
-		pcie_phy_dump_test_cntrl(dev, 0, 0, 0, 0);
-
-		for (i = 0; i < 8; i += 4) {
-			write_val = 0x1 + i;
-			msm_pcie_write_reg(dev->phy,
-				PCIE_MISC_N_DEBUG_BUS_BYTE0_INDEX(dev->rc_idx,
-					dev->common_phy), write_val);
-			msm_pcie_write_reg(dev->phy,
-				PCIE_MISC_N_DEBUG_BUS_BYTE1_INDEX(dev->rc_idx,
-					dev->common_phy), write_val + 1);
-			msm_pcie_write_reg(dev->phy,
-				PCIE_MISC_N_DEBUG_BUS_BYTE2_INDEX(dev->rc_idx,
-					dev->common_phy), write_val + 2);
-			msm_pcie_write_reg(dev->phy,
-				PCIE_MISC_N_DEBUG_BUS_BYTE3_INDEX(dev->rc_idx,
-					dev->common_phy), write_val + 3);
-
-			PCIE_DUMP(dev,
-				"PCIe: RC%d to PCIE_MISC_N_DEBUG_BUS_BYTE0_INDEX: 0x%x\n",
-				dev->rc_idx,
-				readl_relaxed(dev->phy +
-					PCIE_MISC_N_DEBUG_BUS_BYTE0_INDEX(
-						dev->rc_idx, dev->common_phy)));
-			PCIE_DUMP(dev,
-				"PCIe: RC%d to PCIE_MISC_N_DEBUG_BUS_BYTE1_INDEX: 0x%x\n",
-				dev->rc_idx,
-				readl_relaxed(dev->phy +
-					PCIE_MISC_N_DEBUG_BUS_BYTE1_INDEX(
-						dev->rc_idx, dev->common_phy)));
-			PCIE_DUMP(dev,
-				"PCIe: RC%d to PCIE_MISC_N_DEBUG_BUS_BYTE2_INDEX: 0x%x\n",
-				dev->rc_idx,
-				readl_relaxed(dev->phy +
-					PCIE_MISC_N_DEBUG_BUS_BYTE2_INDEX(
-						dev->rc_idx, dev->common_phy)));
-			PCIE_DUMP(dev,
-				"PCIe: RC%d to PCIE_MISC_N_DEBUG_BUS_BYTE3_INDEX: 0x%x\n",
-				dev->rc_idx,
-				readl_relaxed(dev->phy +
-					PCIE_MISC_N_DEBUG_BUS_BYTE3_INDEX(
-						dev->rc_idx, dev->common_phy)));
-			PCIE_DUMP(dev,
-				"PCIe: RC%d PCIE_MISC_N_DEBUG_BUS_0_STATUS: 0x%x\n",
-				dev->rc_idx,
-				readl_relaxed(dev->phy +
-					PCIE_MISC_N_DEBUG_BUS_0_STATUS(
-						dev->rc_idx, dev->common_phy)));
-			PCIE_DUMP(dev,
-				"PCIe: RC%d PCIE_MISC_N_DEBUG_BUS_1_STATUS: 0x%x\n",
-				dev->rc_idx,
-				readl_relaxed(dev->phy +
-					PCIE_MISC_N_DEBUG_BUS_1_STATUS(
-						dev->rc_idx, dev->common_phy)));
-			PCIE_DUMP(dev,
-				"PCIe: RC%d PCIE_MISC_N_DEBUG_BUS_2_STATUS: 0x%x\n",
-				dev->rc_idx,
-				readl_relaxed(dev->phy +
-					PCIE_MISC_N_DEBUG_BUS_2_STATUS(
-						dev->rc_idx, dev->common_phy)));
-			PCIE_DUMP(dev,
-				"PCIe: RC%d PCIE_MISC_N_DEBUG_BUS_3_STATUS: 0x%x\n",
-				dev->rc_idx,
-				readl_relaxed(dev->phy +
-					PCIE_MISC_N_DEBUG_BUS_3_STATUS(
-						dev->rc_idx, dev->common_phy)));
-		}
-
-		msm_pcie_write_reg(dev->phy,
-			PCIE_MISC_N_DEBUG_BUS_BYTE0_INDEX(
-				dev->rc_idx, dev->common_phy), 0);
-		msm_pcie_write_reg(dev->phy,
-			PCIE_MISC_N_DEBUG_BUS_BYTE1_INDEX(
-				dev->rc_idx, dev->common_phy), 0);
-		msm_pcie_write_reg(dev->phy,
-			PCIE_MISC_N_DEBUG_BUS_BYTE2_INDEX(
-				dev->rc_idx, dev->common_phy), 0);
-		msm_pcie_write_reg(dev->phy,
-			PCIE_MISC_N_DEBUG_BUS_BYTE3_INDEX(
-				dev->rc_idx, dev->common_phy), 0);
-	}
-
-	for (i = 0; i < 2; i++) {
-		write_val = 0x2 + i;
-
-		msm_pcie_write_reg(dev->phy, QSERDES_COM_DEBUG_BUS_SEL,
-			write_val);
-
-		PCIE_DUMP(dev,
-			"PCIe: RC%d to QSERDES_COM_DEBUG_BUS_SEL: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy + QSERDES_COM_DEBUG_BUS_SEL));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d QSERDES_COM_DEBUG_BUS0: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy + QSERDES_COM_DEBUG_BUS0));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d QSERDES_COM_DEBUG_BUS1: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy + QSERDES_COM_DEBUG_BUS1));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d QSERDES_COM_DEBUG_BUS2: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy + QSERDES_COM_DEBUG_BUS2));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d QSERDES_COM_DEBUG_BUS3: 0x%x\n\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy + QSERDES_COM_DEBUG_BUS3));
-	}
-
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_DEBUG_BUS_SEL, 0);
-
-	if (dev->common_phy) {
-		msm_pcie_write_reg(dev->phy, PCIE_COM_DEBUG_BUS_BYTE0_INDEX,
-			0x01);
-		msm_pcie_write_reg(dev->phy, PCIE_COM_DEBUG_BUS_BYTE1_INDEX,
-			0x02);
-		msm_pcie_write_reg(dev->phy, PCIE_COM_DEBUG_BUS_BYTE2_INDEX,
-			0x03);
-		msm_pcie_write_reg(dev->phy, PCIE_COM_DEBUG_BUS_BYTE3_INDEX,
-			0x04);
-
-		PCIE_DUMP(dev,
-			"PCIe: RC%d to PCIE_COM_DEBUG_BUS_BYTE0_INDEX: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy +
-				PCIE_COM_DEBUG_BUS_BYTE0_INDEX));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d to PCIE_COM_DEBUG_BUS_BYTE1_INDEX: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy +
-				PCIE_COM_DEBUG_BUS_BYTE1_INDEX));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d to PCIE_COM_DEBUG_BUS_BYTE2_INDEX: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy +
-				PCIE_COM_DEBUG_BUS_BYTE2_INDEX));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d to PCIE_COM_DEBUG_BUS_BYTE3_INDEX: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy +
-				PCIE_COM_DEBUG_BUS_BYTE3_INDEX));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d PCIE_COM_DEBUG_BUS_0_STATUS: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy +
-				PCIE_COM_DEBUG_BUS_0_STATUS));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d PCIE_COM_DEBUG_BUS_1_STATUS: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy +
-				PCIE_COM_DEBUG_BUS_1_STATUS));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d PCIE_COM_DEBUG_BUS_2_STATUS: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy +
-				PCIE_COM_DEBUG_BUS_2_STATUS));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d PCIE_COM_DEBUG_BUS_3_STATUS: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy +
-				PCIE_COM_DEBUG_BUS_3_STATUS));
-
-		msm_pcie_write_reg(dev->phy, PCIE_COM_DEBUG_BUS_BYTE0_INDEX,
-			0x05);
-
-		PCIE_DUMP(dev,
-			"PCIe: RC%d to PCIE_COM_DEBUG_BUS_BYTE0_INDEX: 0x%x\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy +
-				PCIE_COM_DEBUG_BUS_BYTE0_INDEX));
-		PCIE_DUMP(dev,
-			"PCIe: RC%d PCIE_COM_DEBUG_BUS_0_STATUS: 0x%x\n\n",
-			dev->rc_idx,
-			readl_relaxed(dev->phy +
-				PCIE_COM_DEBUG_BUS_0_STATUS));
-	}
 
 	size = resource_size(dev->res[MSM_PCIE_RES_PHY].resource);
 	for (i = 0; i < size; i += 32) {
@@ -1342,181 +829,6 @@
 	}
 }
 
-#ifdef CONFIG_ARCH_MDMCALIFORNIUM
-static void pcie_phy_init(struct msm_pcie_dev_t *dev)
-{
-	u8 common_phy;
-
-	PCIE_DBG(dev,
-		"RC%d: Initializing MDM 14nm QMP phy - 19.2MHz with Common Mode Clock (SSC ON)\n",
-		dev->rc_idx);
-
-	if (dev->common_phy)
-		common_phy = 1;
-	else
-		common_phy = 0;
-
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_SW_RESET(dev->rc_idx, common_phy),
-		0x01);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_POWER_DOWN_CONTROL(dev->rc_idx, common_phy),
-		0x03);
-
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_ENABLE1, 0x10);
-
-	msm_pcie_write_reg(dev->phy,
-			QSERDES_TX_N_LANE_MODE(dev->rc_idx, common_phy), 0x06);
-
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP_EN, 0x01);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_MAP, 0x00);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_TIMER1, 0xFF);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_TIMER2, 0x1F);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_BG_TRIM, 0x0F);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_IVCO, 0x0F);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_HSCLK_SEL, 0x00);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SVS_MODE_CLK_SEL, 0x01);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CORE_CLK_EN, 0x20);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CORECLK_DIV, 0x0A);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_BG_TIMER, 0x09);
-
-	if (dev->tcsr) {
-		PCIE_DBG(dev, "RC%d: TCSR PHY clock scheme is 0x%x\n",
-			dev->rc_idx, readl_relaxed(dev->tcsr));
-
-		if (readl_relaxed(dev->tcsr) & (BIT(1) | BIT(0)))
-			msm_pcie_write_reg(dev->phy,
-					QSERDES_COM_SYSCLK_EN_SEL, 0x0A);
-		else
-			msm_pcie_write_reg(dev->phy,
-					QSERDES_COM_SYSCLK_EN_SEL, 0x04);
-	}
-
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_DEC_START_MODE0, 0x82);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP3_MODE0, 0x00);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP2_MODE0, 0x0D);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP1_MODE0, 0x04);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_SELECT, 0x33);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SYS_CLK_CTRL, 0x02);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1F);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CP_CTRL_MODE0, 0x0B);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_CCTRL_MODE0, 0x28);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80);
-
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_EN_CENTER, 0x01);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_PER1, 0x31);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_PER2, 0x01);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_ADJ_PER1, 0x02);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_ADJ_PER2, 0x00);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_STEP_SIZE1, 0x2f);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_STEP_SIZE2, 0x19);
-
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_TX_N_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN(dev->rc_idx,
-		common_phy), 0x45);
-
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CMN_CONFIG, 0x06);
-
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_TX_N_RES_CODE_LANE_OFFSET(dev->rc_idx, common_phy),
-		0x02);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_TX_N_RCV_DETECT_LVL_2(dev->rc_idx, common_phy),
-		0x12);
-
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_SIGDET_ENABLES(dev->rc_idx, common_phy),
-		0x1C);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_SIGDET_DEGLITCH_CNTRL(dev->rc_idx, common_phy),
-		0x14);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL2(dev->rc_idx, common_phy),
-		0x01);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL3(dev->rc_idx, common_phy),
-		0x00);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL4(dev->rc_idx, common_phy),
-		0xDB);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_UCDR_SO_SATURATION_AND_ENABLE(dev->rc_idx,
-		common_phy),
-		0x4B);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_UCDR_SO_GAIN(dev->rc_idx, common_phy),
-		0x04);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_UCDR_SO_GAIN_HALF(dev->rc_idx, common_phy),
-		0x04);
-
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_EP_DIV, 0x19);
-
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_ENDPOINT_REFCLK_DRIVE(dev->rc_idx, common_phy),
-		0x04);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_OSC_DTCT_ACTIONS(dev->rc_idx, common_phy),
-		0x00);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_PWRUP_RESET_DLY_TIME_AUXCLK(dev->rc_idx, common_phy),
-		0x40);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB(dev->rc_idx, common_phy),
-		0x00);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB(dev->rc_idx, common_phy),
-		0x40);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_LP_WAKEUP_DLY_TIME_AUXCLK_MSB(dev->rc_idx, common_phy),
-		0x00);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_LP_WAKEUP_DLY_TIME_AUXCLK(dev->rc_idx, common_phy),
-		0x40);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_PLL_LOCK_CHK_DLY_TIME(dev->rc_idx, common_phy),
-		0x73);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_SIGDET_LVL(dev->rc_idx, common_phy),
-		0x99);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_TXDEEMPH_M6DB_V0(dev->rc_idx, common_phy),
-		0x15);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_TXDEEMPH_M3P5DB_V0(dev->rc_idx, common_phy),
-		0x0E);
-
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_SIGDET_CNTRL(dev->rc_idx, common_phy),
-		0x07);
-
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_SW_RESET(dev->rc_idx, common_phy),
-		0x00);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_START_CONTROL(dev->rc_idx, common_phy),
-		0x03);
-}
-
-static void pcie_pcs_port_phy_init(struct msm_pcie_dev_t *dev)
-{
-}
-
-static bool pcie_phy_is_ready(struct msm_pcie_dev_t *dev)
-{
-	if (readl_relaxed(dev->phy +
-		PCIE_N_PCS_STATUS(dev->rc_idx, dev->common_phy)) & BIT(6))
-		return false;
-	else
-		return true;
-}
-#else
 static void pcie_phy_init(struct msm_pcie_dev_t *dev)
 {
 	int i;
@@ -1538,64 +850,6 @@
 					phy_seq->delay + 1);
 			phy_seq++;
 		}
-		return;
-	}
-
-	if (dev->common_phy)
-		msm_pcie_write_reg(dev->phy, PCIE_COM_POWER_DOWN_CONTROL, 0x01);
-
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1C);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_ENABLE1, 0x10);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_SELECT, 0x33);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CMN_CONFIG, 0x06);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP_EN, 0x42);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_MAP, 0x00);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_TIMER1, 0xFF);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_VCO_TUNE_TIMER2, 0x1F);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_HSCLK_SEL, 0x01);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SVS_MODE_CLK_SEL, 0x01);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CORE_CLK_EN, 0x00);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CORECLK_DIV, 0x0A);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_BG_TIMER, 0x09);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_DEC_START_MODE0, 0x82);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP3_MODE0, 0x00);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP2_MODE0, 0x1A);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_LOCK_CMP1_MODE0, 0x0A);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_SELECT, 0x33);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SYS_CLK_CTRL, 0x02);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1F);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SYSCLK_EN_SEL, 0x04);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CP_CTRL_MODE0, 0x0B);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_CCTRL_MODE0, 0x28);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_EN_CENTER, 0x01);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_PER1, 0x31);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_PER2, 0x01);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_ADJ_PER1, 0x02);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_ADJ_PER2, 0x00);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_STEP_SIZE1, 0x2f);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_SSC_STEP_SIZE2, 0x19);
-
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_RESCODE_DIV_NUM, 0x15);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_BG_TRIM, 0x0F);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_PLL_IVCO, 0x0F);
-
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_EP_DIV, 0x19);
-	msm_pcie_write_reg(dev->phy, QSERDES_COM_CLK_ENABLE1, 0x10);
-
-	if (dev->phy_ver == 0x3) {
-		msm_pcie_write_reg(dev->phy, QSERDES_COM_HSCLK_SEL, 0x00);
-		msm_pcie_write_reg(dev->phy, QSERDES_COM_RESCODE_DIV_NUM, 0x40);
-	}
-
-	if (dev->common_phy) {
-		msm_pcie_write_reg(dev->phy, PCIE_COM_SW_RESET, 0x00);
-		msm_pcie_write_reg(dev->phy, PCIE_COM_START_CONTROL, 0x03);
 	}
 }
 
@@ -1603,18 +857,9 @@
 {
 	int i;
 	struct msm_pcie_phy_info_t *phy_seq;
-	u8 common_phy;
-
-	if (dev->phy_ver >= 0x20)
-		return;
 
 	PCIE_DBG(dev, "RC%d: Initializing PCIe PHY Port\n", dev->rc_idx);
 
-	if (dev->common_phy)
-		common_phy = 1;
-	else
-		common_phy = 0;
-
 	if (dev->port_phy_sequence) {
 		i =  dev->port_phy_len;
 		phy_seq = dev->port_phy_sequence;
@@ -1627,93 +872,8 @@
 					phy_seq->delay + 1);
 			phy_seq++;
 		}
-		return;
 	}
 
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_TX_N_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN(dev->rc_idx,
-		common_phy), 0x45);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_TX_N_LANE_MODE(dev->rc_idx, common_phy),
-		0x06);
-
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_SIGDET_ENABLES(dev->rc_idx, common_phy),
-		0x1C);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_SIGDET_LVL(dev->rc_idx, common_phy),
-		0x17);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL2(dev->rc_idx, common_phy),
-		0x01);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL3(dev->rc_idx, common_phy),
-		0x00);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_RX_EQU_ADAPTOR_CNTRL4(dev->rc_idx, common_phy),
-		0xDB);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_RX_BAND(dev->rc_idx, common_phy),
-		0x18);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_UCDR_SO_GAIN(dev->rc_idx, common_phy),
-		0x04);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_UCDR_SO_GAIN_HALF(dev->rc_idx, common_phy),
-		0x04);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_RX_IDLE_DTCT_CNTRL(dev->rc_idx, common_phy),
-		0x4C);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_PWRUP_RESET_DLY_TIME_AUXCLK(dev->rc_idx, common_phy),
-		0x00);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_LP_WAKEUP_DLY_TIME_AUXCLK(dev->rc_idx, common_phy),
-		0x01);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_PLL_LOCK_CHK_DLY_TIME(dev->rc_idx, common_phy),
-		0x05);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_UCDR_SO_SATURATION_AND_ENABLE(dev->rc_idx,
-		common_phy), 0x4B);
-	msm_pcie_write_reg(dev->phy,
-		QSERDES_RX_N_SIGDET_DEGLITCH_CNTRL(dev->rc_idx, common_phy),
-		0x14);
-
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_ENDPOINT_REFCLK_DRIVE(dev->rc_idx, common_phy),
-		0x05);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_POWER_DOWN_CONTROL(dev->rc_idx, common_phy),
-		0x02);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_POWER_STATE_CONFIG4(dev->rc_idx, common_phy),
-		0x00);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_POWER_STATE_CONFIG1(dev->rc_idx, common_phy),
-		0xA3);
-
-	if (dev->phy_ver == 0x3) {
-		msm_pcie_write_reg(dev->phy,
-			QSERDES_RX_N_SIGDET_LVL(dev->rc_idx, common_phy),
-			0x19);
-
-		msm_pcie_write_reg(dev->phy,
-			PCIE_N_TXDEEMPH_M3P5DB_V0(dev->rc_idx, common_phy),
-			0x0E);
-	}
-
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_POWER_DOWN_CONTROL(dev->rc_idx, common_phy),
-		0x03);
-	usleep_range(POWER_DOWN_DELAY_US_MIN, POWER_DOWN_DELAY_US_MAX);
-
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_SW_RESET(dev->rc_idx, common_phy),
-		0x00);
-	msm_pcie_write_reg(dev->phy,
-		PCIE_N_START_CONTROL(dev->rc_idx, common_phy),
-		0x0A);
 }
 
 static bool pcie_phy_is_ready(struct msm_pcie_dev_t *dev)
@@ -1732,8 +892,6 @@
 	else
 		return true;
 }
-#endif
-#endif
 
 static int msm_pcie_restore_sec_config(struct msm_pcie_dev_t *dev)
 {
@@ -1975,8 +1133,6 @@
 		dev->msi_gicm_base);
 	PCIE_DBG_FS(dev, "bus_client: %d\n",
 		dev->bus_client);
-	PCIE_DBG_FS(dev, "current short bdf: %d\n",
-		dev->current_short_bdf);
 	PCIE_DBG_FS(dev, "smmu does %s exist\n",
 		dev->smmu_exist ? "" : "not");
 	PCIE_DBG_FS(dev, "smmu_sid_base: 0x%x\n",
@@ -3512,8 +2668,8 @@
 						dev->rc_idx,
 						dev->vreg[i].name);
 					regulator_set_voltage(hdl,
-						RPM_REGULATOR_CORNER_NONE,
-						INT_MAX);
+						RPMH_REGULATOR_LEVEL_OFF,
+						RPMH_REGULATOR_LEVEL_MAX);
 				}
 			}
 
@@ -3542,8 +2698,8 @@
 					dev->rc_idx,
 					dev->vreg[i].name);
 				regulator_set_voltage(dev->vreg[i].hdl,
-					RPM_REGULATOR_CORNER_NONE,
-					INT_MAX);
+					RPMH_REGULATOR_LEVEL_OFF,
+					RPMH_REGULATOR_LEVEL_MAX);
 			}
 		}
 	}
@@ -3645,6 +2801,19 @@
 	for (i = 0; i < MSM_PCIE_MAX_RESET; i++) {
 		reset_info = &dev->reset[i];
 		if (reset_info->hdl) {
+			rc = reset_control_assert(reset_info->hdl);
+			if (rc)
+				PCIE_ERR(dev,
+					"PCIe: RC%d failed to assert reset for %s.\n",
+					dev->rc_idx, reset_info->name);
+			else
+				PCIE_DBG2(dev,
+					"PCIe: RC%d successfully asserted reset for %s.\n",
+					dev->rc_idx, reset_info->name);
+
+			/* add a 1ms delay to ensure the reset is asserted */
+			usleep_range(1000, 1005);
+
 			rc = reset_control_deassert(reset_info->hdl);
 			if (rc)
 				PCIE_ERR(dev,
@@ -3749,6 +2918,19 @@
 	for (i = 0; i < MSM_PCIE_MAX_PIPE_RESET; i++) {
 		pipe_reset_info = &dev->pipe_reset[i];
 		if (pipe_reset_info->hdl) {
+			rc = reset_control_assert(pipe_reset_info->hdl);
+			if (rc)
+				PCIE_ERR(dev,
+					"PCIe: RC%d failed to assert pipe reset for %s.\n",
+					dev->rc_idx, pipe_reset_info->name);
+			else
+				PCIE_DBG2(dev,
+					"PCIe: RC%d successfully asserted pipe reset for %s.\n",
+					dev->rc_idx, pipe_reset_info->name);
+
+			/* add a 1ms delay to ensure the reset is asserted */
+			usleep_range(1000, 1005);
+
 			rc = reset_control_deassert(
 					pipe_reset_info->hdl);
 			if (rc)
@@ -3802,8 +2984,6 @@
 
 static void msm_pcie_config_controller(struct msm_pcie_dev_t *dev)
 {
-	int i;
-
 	PCIE_DBG(dev, "RC%d\n", dev->rc_idx);
 
 	/*
@@ -3859,27 +3039,6 @@
 		PCIE_DBG(dev, "RC's PCIE20_CAP_DEVCTRLSTATUS:0x%x\n",
 			readl_relaxed(dev->dm_core + PCIE20_CAP_DEVCTRLSTATUS));
 	}
-
-	/* configure SMMU registers */
-	if (dev->smmu_exist) {
-		msm_pcie_write_reg(dev->parf,
-			PCIE20_PARF_BDF_TRANSLATE_CFG, 0);
-		msm_pcie_write_reg(dev->parf,
-			PCIE20_PARF_SID_OFFSET, 0);
-
-		if (dev->enumerated) {
-			for (i = 0; i < MAX_DEVICE_NUM; i++) {
-				if (dev->pcidev_table[i].dev &&
-					dev->pcidev_table[i].short_bdf) {
-					msm_pcie_write_reg(dev->parf,
-						PCIE20_PARF_BDF_TRANSLATE_N +
-						dev->pcidev_table[i].short_bdf
-						* 4,
-						dev->pcidev_table[i].bdf >> 16);
-				}
-			}
-		}
-	}
 }
 
 static void msm_pcie_config_link_state(struct msm_pcie_dev_t *dev)
@@ -4527,6 +3686,13 @@
 		msm_pcie_restore_sec_config(dev);
 	}
 
+	/* configure PCIe to RC mode */
+	msm_pcie_write_reg(dev->parf, PCIE20_PARF_DEVICE_TYPE, 0x4);
+
+	/* enable l1 mode, clear bit 5 (REQ_NOT_ENTR_L1) */
+	if (dev->l1_supported)
+		msm_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, BIT(5), 0);
+
 	/* enable PCIe clocks and resets */
 	msm_pcie_write_mask(dev->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0);
 
@@ -4688,6 +3854,9 @@
 
 	msm_pcie_config_link_state(dev);
 
+	if (dev->enumerated)
+		pci_walk_bus(dev->dev->bus, &msm_pcie_config_device, dev);
+
 	dev->link_status = MSM_PCIE_LINK_ENABLED;
 	dev->power_on = true;
 	dev->suspending = false;
@@ -4935,106 +4104,41 @@
 	return ret;
 }
 
-int msm_pcie_configure_sid(struct device *dev, u32 *sid, int *domain)
+static void msm_pcie_configure_sid(struct msm_pcie_dev_t *pcie_dev,
+				struct pci_dev *dev)
 {
-	struct pci_dev *pcidev;
-	struct msm_pcie_dev_t *pcie_dev;
-	struct pci_bus *bus;
-	int i;
+	u32 offset;
+	u32 sid;
 	u32 bdf;
+	int ret;
 
-	if (!dev) {
-		pr_err("%s: PCIe: endpoint device passed in is NULL\n",
-			__func__);
-		return MSM_PCIE_ERROR;
-	}
-
-	pcidev = to_pci_dev(dev);
-	if (!pcidev) {
-		pr_err("%s: PCIe: PCI device of endpoint is NULL\n",
-			__func__);
-		return MSM_PCIE_ERROR;
-	}
-
-	bus = pcidev->bus;
-	if (!bus) {
-		pr_err("%s: PCIe: Bus of PCI device is NULL\n",
-			__func__);
-		return MSM_PCIE_ERROR;
-	}
-
-	while (!pci_is_root_bus(bus))
-		bus = bus->parent;
-
-	pcie_dev = (struct msm_pcie_dev_t *)(bus->sysdata);
-	if (!pcie_dev) {
-		pr_err("%s: PCIe: Could not get PCIe structure\n",
-			__func__);
-		return MSM_PCIE_ERROR;
-	}
-
-	if (!pcie_dev->smmu_exist) {
+	ret = iommu_fwspec_get_id(&dev->dev, &sid);
+	if (ret) {
 		PCIE_DBG(pcie_dev,
-			"PCIe: RC:%d: smmu does not exist\n",
+			"PCIe: RC%d: Device does not have a SID\n",
 			pcie_dev->rc_idx);
-		return MSM_PCIE_ERROR;
-	}
-
-	PCIE_DBG(pcie_dev, "PCIe: RC%d: device address is: %p\n",
-		pcie_dev->rc_idx, dev);
-	PCIE_DBG(pcie_dev, "PCIe: RC%d: PCI device address is: %p\n",
-		pcie_dev->rc_idx, pcidev);
-
-	*domain = pcie_dev->rc_idx;
-
-	if (pcie_dev->current_short_bdf < (MAX_SHORT_BDF_NUM - 1)) {
-		pcie_dev->current_short_bdf++;
-	} else {
-		PCIE_ERR(pcie_dev,
-			"PCIe: RC%d: No more short BDF left\n",
-			pcie_dev->rc_idx);
-		return MSM_PCIE_ERROR;
-	}
-
-	bdf = BDF_OFFSET(pcidev->bus->number, pcidev->devfn);
-
-	for (i = 0; i < MAX_DEVICE_NUM; i++) {
-		if (pcie_dev->pcidev_table[i].bdf == bdf) {
-			*sid = pcie_dev->smmu_sid_base +
-				((pcie_dev->rc_idx << 4) |
-				pcie_dev->current_short_bdf);
-
-			msm_pcie_write_reg(pcie_dev->parf,
-				PCIE20_PARF_BDF_TRANSLATE_N +
-				pcie_dev->current_short_bdf * 4,
-				bdf >> 16);
-
-			pcie_dev->pcidev_table[i].sid = *sid;
-			pcie_dev->pcidev_table[i].short_bdf =
-				pcie_dev->current_short_bdf;
-			break;
-		}
-	}
-
-	if (i == MAX_DEVICE_NUM) {
-		pcie_dev->current_short_bdf--;
-		PCIE_ERR(pcie_dev,
-			"PCIe: RC%d could not find BDF:%d\n",
-			pcie_dev->rc_idx, bdf);
-		return MSM_PCIE_ERROR;
+		return;
 	}
 
 	PCIE_DBG(pcie_dev,
-		"PCIe: RC%d: Device: %02x:%02x.%01x received SID %d\n",
-		pcie_dev->rc_idx,
-		bdf >> 24,
-		bdf >> 19 & 0x1f,
-		bdf >> 16 & 0x07,
-		*sid);
+		"PCIe: RC%d: Device SID: 0x%x\n",
+		pcie_dev->rc_idx, sid);
 
-	return 0;
+	bdf = BDF_OFFSET(dev->bus->number, dev->devfn);
+	offset = (sid - pcie_dev->smmu_sid_base) * 4;
+
+	if (offset >= MAX_SHORT_BDF_NUM * 4) {
+		PCIE_ERR(pcie_dev,
+			"PCIe: RC%d: Invalid SID offset: 0x%x. Should be less than 0x%x\n",
+			pcie_dev->rc_idx, offset, MAX_SHORT_BDF_NUM * 4);
+		return;
+	}
+
+	msm_pcie_write_reg(pcie_dev->parf, PCIE20_PARF_BDF_TRANSLATE_CFG, 0);
+	msm_pcie_write_reg(pcie_dev->parf, PCIE20_PARF_SID_OFFSET, 0);
+	msm_pcie_write_reg(pcie_dev->parf,
+		PCIE20_PARF_BDF_TRANSLATE_N + offset, bdf >> 16);
 }
-EXPORT_SYMBOL(msm_pcie_configure_sid);
 
 int msm_pcie_enumerate(u32 rc_idx)
 {
@@ -6138,6 +5242,28 @@
 		disable_irq(dev->wake_n);
 }
 
+static int msm_pcie_config_device(struct pci_dev *dev, void *pdev)
+{
+	struct msm_pcie_dev_t *pcie_dev = (struct msm_pcie_dev_t *)pdev;
+	u8 busnr = dev->bus->number;
+	u8 slot = PCI_SLOT(dev->devfn);
+	u8 func = PCI_FUNC(dev->devfn);
+
+	PCIE_DBG(pcie_dev, "PCIe: RC%d: configure PCI device %02x:%02x.%01x\n",
+		pcie_dev->rc_idx, busnr, slot, func);
+
+	msm_pcie_configure_sid(pcie_dev, dev);
+
+	return 0;
+}
+
+/* Hook to setup PCI device during PCI framework scan */
+int pcibios_add_device(struct pci_dev *dev)
+{
+	struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev->bus);
+
+	return msm_pcie_config_device(dev, pcie_dev);
+}
 
 static int msm_pcie_probe(struct platform_device *pdev)
 {
@@ -6413,7 +5539,6 @@
 	msm_pcie_dev[rc_idx].wake_counter = 0;
 	msm_pcie_dev[rc_idx].aer_enable = true;
 	msm_pcie_dev[rc_idx].power_on = false;
-	msm_pcie_dev[rc_idx].current_short_bdf = 0;
 	msm_pcie_dev[rc_idx].use_msi = false;
 	msm_pcie_dev[rc_idx].use_pinctrl = false;
 	msm_pcie_dev[rc_idx].linkdown_panic = false;
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c
index 67adf58..30c31a8 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm845.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c
@@ -526,7 +526,6 @@
 	msm_mux_reserved30,
 	msm_mux_qup11,
 	msm_mux_qup14,
-	msm_mux_phase_flag3,
 	msm_mux_reserved96,
 	msm_mux_ldo_en,
 	msm_mux_reserved97,
@@ -543,17 +542,13 @@
 	msm_mux_phase_flag5,
 	msm_mux_reserved103,
 	msm_mux_reserved104,
-	msm_mux_pcie1_forceon,
 	msm_mux_uim2_data,
 	msm_mux_qup13,
 	msm_mux_reserved105,
-	msm_mux_pcie1_pwren,
 	msm_mux_uim2_clk,
 	msm_mux_reserved106,
-	msm_mux_pcie1_auxen,
 	msm_mux_uim2_reset,
 	msm_mux_reserved107,
-	msm_mux_pcie1_button,
 	msm_mux_uim2_present,
 	msm_mux_reserved108,
 	msm_mux_uim1_data,
@@ -564,7 +559,6 @@
 	msm_mux_reserved111,
 	msm_mux_uim1_present,
 	msm_mux_reserved112,
-	msm_mux_pcie1_prsnt2,
 	msm_mux_uim_batt,
 	msm_mux_edp_hot,
 	msm_mux_reserved113,
@@ -587,7 +581,6 @@
 	msm_mux_reserved123,
 	msm_mux_reserved124,
 	msm_mux_reserved125,
-	msm_mux_sd_card,
 	msm_mux_reserved126,
 	msm_mux_reserved127,
 	msm_mux_reserved128,
@@ -647,7 +640,6 @@
 	msm_mux_reserved42,
 	msm_mux_reserved43,
 	msm_mux_reserved44,
-	msm_mux_bt_reset,
 	msm_mux_qup6,
 	msm_mux_reserved45,
 	msm_mux_reserved46,
@@ -672,7 +664,6 @@
 	msm_mux_gcc_gp1,
 	msm_mux_phase_flag18,
 	msm_mux_reserved57,
-	msm_mux_ssc_irq,
 	msm_mux_phase_flag19,
 	msm_mux_reserved58,
 	msm_mux_phase_flag20,
@@ -731,10 +722,8 @@
 	msm_mux_reserved82,
 	msm_mux_reserved83,
 	msm_mux_reserved84,
-	msm_mux_pcie1_pwrfault,
 	msm_mux_qup5,
 	msm_mux_reserved85,
-	msm_mux_pcie1_mrl,
 	msm_mux_reserved86,
 	msm_mux_reserved87,
 	msm_mux_reserved88,
@@ -772,6 +761,7 @@
 	msm_mux_reserved95,
 	msm_mux_tsif2_sync,
 	msm_mux_sdc40,
+	msm_mux_phase_flag3,
 	msm_mux_NA,
 };
 
@@ -781,19 +771,24 @@
 	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
 	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
 	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
-	"gpio36", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43",
-	"gpio44", "gpio46", "gpio47", "gpio48", "gpio49", "gpio50", "gpio51",
-	"gpio52", "gpio53", "gpio54", "gpio55", "gpio56", "gpio57", "gpio64",
-	"gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", "gpio71",
-	"gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", "gpio81",
-	"gpio82", "gpio83", "gpio84", "gpio87", "gpio88", "gpio89", "gpio90",
-	"gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97",
-	"gpio98", "gpio99", "gpio100", "gpio101", "gpio102", "gpio103",
-	"gpio109", "gpio110", "gpio111", "gpio112", "gpio114", "gpio115",
-	"gpio116", "gpio127", "gpio128", "gpio129", "gpio130", "gpio131",
-	"gpio132", "gpio133", "gpio134", "gpio135", "gpio136", "gpio137",
-	"gpio138", "gpio139", "gpio140", "gpio141", "gpio142", "gpio143",
-	"gpio144", "gpio145", "gpio146", "gpio147", "gpio148", "gpio149",
+	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+	"gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+	"gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+	"gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+	"gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+	"gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+	"gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+	"gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+	"gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+	"gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+	"gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+	"gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+	"gpio141", "gpio142", "gpio143", "gpio144", "gpio145", "gpio146",
+	"gpio147", "gpio148", "gpio149",
 };
 static const char * const qup0_groups[] = {
 	"gpio0", "gpio1", "gpio2", "gpio3",
@@ -1075,9 +1070,6 @@
 static const char * const qup14_groups[] = {
 	"gpio31", "gpio32", "gpio33", "gpio34",
 };
-static const char * const phase_flag3_groups[] = {
-	"gpio96",
-};
 static const char * const reserved96_groups[] = {
 	"gpio96",
 };
@@ -1109,7 +1101,7 @@
 	"gpio101",
 };
 static const char * const pci_e1_groups[] = {
-	"gpio102", "gpio103", "gpio104",
+	"gpio102", "gpio103",
 };
 static const char * const prng_rosc_groups[] = {
 	"gpio102",
@@ -1126,9 +1118,6 @@
 static const char * const reserved104_groups[] = {
 	"gpio104",
 };
-static const char * const pcie1_forceon_groups[] = {
-	"gpio105",
-};
 static const char * const uim2_data_groups[] = {
 	"gpio105",
 };
@@ -1138,27 +1127,18 @@
 static const char * const reserved105_groups[] = {
 	"gpio105",
 };
-static const char * const pcie1_pwren_groups[] = {
-	"gpio106",
-};
 static const char * const uim2_clk_groups[] = {
 	"gpio106",
 };
 static const char * const reserved106_groups[] = {
 	"gpio106",
 };
-static const char * const pcie1_auxen_groups[] = {
-	"gpio107",
-};
 static const char * const uim2_reset_groups[] = {
 	"gpio107",
 };
 static const char * const reserved107_groups[] = {
 	"gpio107",
 };
-static const char * const pcie1_button_groups[] = {
-	"gpio108",
-};
 static const char * const uim2_present_groups[] = {
 	"gpio108",
 };
@@ -1189,9 +1169,6 @@
 static const char * const reserved112_groups[] = {
 	"gpio112",
 };
-static const char * const pcie1_prsnt2_groups[] = {
-	"gpio113",
-};
 static const char * const uim_batt_groups[] = {
 	"gpio113",
 };
@@ -1259,9 +1236,6 @@
 static const char * const reserved125_groups[] = {
 	"gpio125",
 };
-static const char * const sd_card_groups[] = {
-	"gpio126",
-};
 static const char * const reserved126_groups[] = {
 	"gpio126",
 };
@@ -1380,7 +1354,7 @@
 	"gpio34",
 };
 static const char * const pci_e0_groups[] = {
-	"gpio35", "gpio36", "gpio37",
+	"gpio35", "gpio36",
 };
 static const char * const jitter_bist_groups[] = {
 	"gpio35",
@@ -1439,9 +1413,6 @@
 static const char * const reserved44_groups[] = {
 	"gpio44",
 };
-static const char * const bt_reset_groups[] = {
-	"gpio45",
-};
 static const char * const qup6_groups[] = {
 	"gpio45", "gpio46", "gpio47", "gpio48",
 };
@@ -1514,11 +1485,6 @@
 static const char * const reserved57_groups[] = {
 	"gpio57",
 };
-static const char * const ssc_irq_groups[] = {
-	"gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", "gpio78",
-	"gpio79", "gpio80", "gpio117", "gpio118", "gpio119", "gpio120",
-	"gpio121", "gpio122", "gpio123", "gpio124", "gpio125",
-};
 static const char * const phase_flag19_groups[] = {
 	"gpio58",
 };
@@ -1693,18 +1659,12 @@
 static const char * const reserved84_groups[] = {
 	"gpio84",
 };
-static const char * const pcie1_pwrfault_groups[] = {
-	"gpio85",
-};
 static const char * const qup5_groups[] = {
 	"gpio85", "gpio86", "gpio87", "gpio88",
 };
 static const char * const reserved85_groups[] = {
 	"gpio85",
 };
-static const char * const pcie1_mrl_groups[] = {
-	"gpio86",
-};
 static const char * const reserved86_groups[] = {
 	"gpio86",
 };
@@ -1816,6 +1776,9 @@
 static const char * const sdc40_groups[] = {
 	"gpio96",
 };
+static const char * const phase_flag3_groups[] = {
+	"gpio96",
+};
 
 static const struct msm_function sdm845_functions[] = {
 	FUNCTION(gpio),
@@ -1912,7 +1875,6 @@
 	FUNCTION(reserved30),
 	FUNCTION(qup11),
 	FUNCTION(qup14),
-	FUNCTION(phase_flag3),
 	FUNCTION(reserved96),
 	FUNCTION(ldo_en),
 	FUNCTION(reserved97),
@@ -1929,17 +1891,13 @@
 	FUNCTION(phase_flag5),
 	FUNCTION(reserved103),
 	FUNCTION(reserved104),
-	FUNCTION(pcie1_forceon),
 	FUNCTION(uim2_data),
 	FUNCTION(qup13),
 	FUNCTION(reserved105),
-	FUNCTION(pcie1_pwren),
 	FUNCTION(uim2_clk),
 	FUNCTION(reserved106),
-	FUNCTION(pcie1_auxen),
 	FUNCTION(uim2_reset),
 	FUNCTION(reserved107),
-	FUNCTION(pcie1_button),
 	FUNCTION(uim2_present),
 	FUNCTION(reserved108),
 	FUNCTION(uim1_data),
@@ -1950,7 +1908,6 @@
 	FUNCTION(reserved111),
 	FUNCTION(uim1_present),
 	FUNCTION(reserved112),
-	FUNCTION(pcie1_prsnt2),
 	FUNCTION(uim_batt),
 	FUNCTION(edp_hot),
 	FUNCTION(reserved113),
@@ -1973,7 +1930,6 @@
 	FUNCTION(reserved123),
 	FUNCTION(reserved124),
 	FUNCTION(reserved125),
-	FUNCTION(sd_card),
 	FUNCTION(reserved126),
 	FUNCTION(reserved127),
 	FUNCTION(reserved128),
@@ -2033,7 +1989,6 @@
 	FUNCTION(reserved42),
 	FUNCTION(reserved43),
 	FUNCTION(reserved44),
-	FUNCTION(bt_reset),
 	FUNCTION(qup6),
 	FUNCTION(reserved45),
 	FUNCTION(reserved46),
@@ -2058,7 +2013,6 @@
 	FUNCTION(gcc_gp1),
 	FUNCTION(phase_flag18),
 	FUNCTION(reserved57),
-	FUNCTION(ssc_irq),
 	FUNCTION(phase_flag19),
 	FUNCTION(reserved58),
 	FUNCTION(phase_flag20),
@@ -2117,10 +2071,8 @@
 	FUNCTION(reserved82),
 	FUNCTION(reserved83),
 	FUNCTION(reserved84),
-	FUNCTION(pcie1_pwrfault),
 	FUNCTION(qup5),
 	FUNCTION(reserved85),
-	FUNCTION(pcie1_mrl),
 	FUNCTION(reserved86),
 	FUNCTION(reserved87),
 	FUNCTION(reserved88),
@@ -2158,6 +2110,7 @@
 	FUNCTION(reserved95),
 	FUNCTION(tsif2_sync),
 	FUNCTION(sdc40),
+	FUNCTION(phase_flag3),
 };
 
 static const struct msm_pingroup sdm845_groups[] = {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
index 19c3de4a..73738bf 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
@@ -53,6 +53,8 @@
 static bool workqueues_stopped;
 static bool ipa3_modem_init_cmplt;
 static bool first_time_handshake;
+struct mutex ipa3_qmi_lock;
+
 /* QMI A5 service */
 
 static struct msg_desc ipa3_indication_reg_req_desc = {
@@ -610,12 +612,17 @@
 		req->filter_spec_ex_list_len);
 	}
 
-	/* cache the qmi_filter_request */
-	memcpy(&(ipa3_qmi_ctx->ipa_install_fltr_rule_req_msg_cache[
-		ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_msg]),
-			req, sizeof(struct ipa_install_fltr_rule_req_msg_v01));
-	ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_msg++;
-	ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_msg %= 10;
+	mutex_lock(&ipa3_qmi_lock);
+	if (ipa3_qmi_ctx != NULL) {
+		/* cache the qmi_filter_request */
+		memcpy(&(ipa3_qmi_ctx->ipa_install_fltr_rule_req_msg_cache[
+			ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_msg]),
+			req,
+			sizeof(struct ipa_install_fltr_rule_req_msg_v01));
+		ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_msg++;
+		ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_msg %= 10;
+	}
+	mutex_unlock(&ipa3_qmi_lock);
 
 	req_desc.max_msg_len = QMI_IPA_INSTALL_FILTER_RULE_REQ_MAX_MSG_LEN_V01;
 	req_desc.msg_id = QMI_IPA_INSTALL_FILTER_RULE_REQ_V01;
@@ -655,12 +662,17 @@
 		req->filter_spec_ex_list_len);
 	}
 
-	/* cache the qmi_filter_request */
-	memcpy(&(ipa3_qmi_ctx->ipa_install_fltr_rule_req_ex_msg_cache[
-		ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_ex_msg]),
-		req, sizeof(struct ipa_install_fltr_rule_req_ex_msg_v01));
-	ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_ex_msg++;
-	ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_ex_msg %= 10;
+	mutex_lock(&ipa3_qmi_lock);
+	if (ipa3_qmi_ctx != NULL) {
+		/* cache the qmi_filter_request */
+		memcpy(&(ipa3_qmi_ctx->ipa_install_fltr_rule_req_ex_msg_cache[
+			ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_ex_msg]),
+			req,
+			sizeof(struct ipa_install_fltr_rule_req_ex_msg_v01));
+		ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_ex_msg++;
+		ipa3_qmi_ctx->num_ipa_install_fltr_rule_req_ex_msg %= 10;
+	}
+	mutex_unlock(&ipa3_qmi_lock);
 
 	req_desc.max_msg_len =
 		QMI_IPA_INSTALL_FILTER_RULE_EX_REQ_MAX_MSG_LEN_V01;
@@ -796,12 +808,17 @@
 		return -EINVAL;
 	}
 
-	/* cache the qmi_filter_request */
-	memcpy(&(ipa3_qmi_ctx->ipa_fltr_installed_notif_req_msg_cache[
-		ipa3_qmi_ctx->num_ipa_fltr_installed_notif_req_msg]),
-		req, sizeof(struct ipa_fltr_installed_notif_req_msg_v01));
-	ipa3_qmi_ctx->num_ipa_fltr_installed_notif_req_msg++;
-	ipa3_qmi_ctx->num_ipa_fltr_installed_notif_req_msg %= 10;
+	mutex_lock(&ipa3_qmi_lock);
+	if (ipa3_qmi_ctx != NULL) {
+		/* cache the qmi_filter_request */
+		memcpy(&(ipa3_qmi_ctx->ipa_fltr_installed_notif_req_msg_cache[
+			ipa3_qmi_ctx->num_ipa_fltr_installed_notif_req_msg]),
+			req,
+			sizeof(struct ipa_fltr_installed_notif_req_msg_v01));
+		ipa3_qmi_ctx->num_ipa_fltr_installed_notif_req_msg++;
+		ipa3_qmi_ctx->num_ipa_fltr_installed_notif_req_msg %= 10;
+	}
+	mutex_unlock(&ipa3_qmi_lock);
 
 	req_desc.max_msg_len =
 	QMI_IPA_FILTER_INSTALLED_NOTIF_REQ_MAX_MSG_LEN_V01;
@@ -1339,3 +1356,13 @@
 		resp.resp.error, "ipa_stop_data_usage_quota_req_msg_v01");
 }
 
+void ipa3_qmi_init(void)
+{
+	mutex_init(&ipa3_qmi_lock);
+}
+
+void ipa3_qmi_cleanup(void)
+{
+	mutex_destroy(&ipa3_qmi_lock);
+}
+
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
index 4fde261..6cd82f8 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
@@ -204,6 +204,10 @@
 
 void ipa3_q6_handshake_complete(bool ssr_bootup);
 
+void ipa3_qmi_init(void);
+
+void ipa3_qmi_cleanup(void);
+
 #else /* CONFIG_RMNET_IPA3 */
 
 static inline int ipa3_qmi_service_init(uint32_t wan_platform_type)
@@ -316,6 +320,14 @@
 
 static inline void ipa3_q6_handshake_complete(bool ssr_bootup) { }
 
+static inline void ipa3_qmi_init(void)
+{
+}
+
+static inline void ipa3_qmi_cleanup(void)
+{
+}
+
 #endif /* CONFIG_RMNET_IPA3 */
 
 #endif /* IPA_QMI_SERVICE_H */
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index 56e7718..a15bd04 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -3206,6 +3206,9 @@
 	mutex_init(&rmnet_ipa3_ctx->pipe_handle_guard);
 	rmnet_ipa3_ctx->ipa3_to_apps_hdl = -1;
 	rmnet_ipa3_ctx->apps_to_ipa3_hdl = -1;
+
+	ipa3_qmi_init();
+
 	/* Register for Modem SSR */
 	rmnet_ipa3_ctx->subsys_notify_handle = subsys_notif_register_notifier(
 			SUBSYS_MODEM,
@@ -3219,7 +3222,7 @@
 static void __exit ipa3_wwan_cleanup(void)
 {
 	int ret;
-
+	ipa3_qmi_cleanup();
 	mutex_destroy(&rmnet_ipa3_ctx->pipe_handle_guard);
 	ret = subsys_notif_unregister_notifier(
 		rmnet_ipa3_ctx->subsys_notify_handle, &ipa3_ssr_notifier);
diff --git a/drivers/platform/msm/msm_11ad/msm_11ad.c b/drivers/platform/msm/msm_11ad/msm_11ad.c
index 47da1b3..5595b7b 100644
--- a/drivers/platform/msm/msm_11ad/msm_11ad.c
+++ b/drivers/platform/msm/msm_11ad/msm_11ad.c
@@ -36,7 +36,7 @@
 #define WIGIG_VENDOR (0x1ae9)
 #define WIGIG_DEVICE (0x0310)
 
-#define SMMU_BASE	0x10000000 /* Device address range base */
+#define SMMU_BASE	0x20000000 /* Device address range base */
 #define SMMU_SIZE	((SZ_1G * 4ULL) - SMMU_BASE)
 
 #define WIGIG_ENABLE_DELAY	50
@@ -93,9 +93,12 @@
 
 	/* SMMU */
 	bool use_smmu; /* have SMMU enabled? */
-	int smmu_bypass;
+	int smmu_s1_en;
 	int smmu_fast_map;
+	int smmu_coherent;
 	struct dma_iommu_mapping *mapping;
+	u32 smmu_base;
+	u32 smmu_size;
 
 	/* bus frequency scaling */
 	struct msm_bus_scale_pdata *bus_scale;
@@ -638,15 +641,20 @@
 {
 	int atomic_ctx = 1;
 	int rc;
+	int force_pt_coherent = 1;
+	int smmu_bypass = !ctx->smmu_s1_en;
+	dma_addr_t iova_base = 0;
+	dma_addr_t iova_end =  ctx->smmu_base + ctx->smmu_size - 1;
+	struct iommu_domain_geometry geometry;
 
 	if (!ctx->use_smmu)
 		return 0;
 
-	dev_info(ctx->dev, "Initialize SMMU, bypass = %d, fastmap = %d\n",
-		 ctx->smmu_bypass, ctx->smmu_fast_map);
+	dev_info(ctx->dev, "Initialize SMMU, bypass=%d, fastmap=%d, coherent=%d\n",
+		 smmu_bypass, ctx->smmu_fast_map, ctx->smmu_coherent);
 
 	ctx->mapping = arm_iommu_create_mapping(&platform_bus_type,
-						SMMU_BASE, SMMU_SIZE);
+						ctx->smmu_base, ctx->smmu_size);
 	if (IS_ERR_OR_NULL(ctx->mapping)) {
 		rc = PTR_ERR(ctx->mapping) ?: -ENODEV;
 		dev_err(ctx->dev, "Failed to create IOMMU mapping (%d)\n", rc);
@@ -662,23 +670,50 @@
 		goto release_mapping;
 	}
 
-	if (ctx->smmu_bypass) {
+	if (smmu_bypass) {
 		rc = iommu_domain_set_attr(ctx->mapping->domain,
 					   DOMAIN_ATTR_S1_BYPASS,
-					   &ctx->smmu_bypass);
+					   &smmu_bypass);
 		if (rc) {
 			dev_err(ctx->dev, "Set bypass attribute to SMMU failed (%d)\n",
 				rc);
 			goto release_mapping;
 		}
-	} else if (ctx->smmu_fast_map) {
-		rc = iommu_domain_set_attr(ctx->mapping->domain,
-					   DOMAIN_ATTR_FAST,
-					   &ctx->smmu_fast_map);
-		if (rc) {
-			dev_err(ctx->dev, "Set fast attribute to SMMU failed (%d)\n",
-				rc);
-			goto release_mapping;
+	} else {
+		/* Set dma-coherent and page table coherency */
+		if (ctx->smmu_coherent) {
+			arch_setup_dma_ops(&ctx->pcidev->dev, 0, 0, NULL, true);
+			rc = iommu_domain_set_attr(ctx->mapping->domain,
+				   DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT,
+				   &force_pt_coherent);
+			if (rc) {
+				dev_err(ctx->dev,
+					"Set SMMU PAGE_TABLE_FORCE_COHERENT attr failed (%d)\n",
+					rc);
+				goto release_mapping;
+			}
+		}
+
+		if (ctx->smmu_fast_map) {
+			rc = iommu_domain_set_attr(ctx->mapping->domain,
+						   DOMAIN_ATTR_FAST,
+						   &ctx->smmu_fast_map);
+			if (rc) {
+				dev_err(ctx->dev, "Set fast attribute to SMMU failed (%d)\n",
+					rc);
+				goto release_mapping;
+			}
+			memset(&geometry, 0, sizeof(geometry));
+			geometry.aperture_start = iova_base;
+			geometry.aperture_end = iova_end;
+			rc = iommu_domain_set_attr(ctx->mapping->domain,
+						   DOMAIN_ATTR_GEOMETRY,
+						   &geometry);
+			if (rc) {
+				dev_err(ctx->dev, "Set geometry attribute to SMMU failed (%d)\n",
+					rc);
+				goto release_mapping;
+			}
 		}
 	}
 
@@ -900,6 +935,7 @@
 	struct device_node *of_node = dev->of_node;
 	struct device_node *rc_node;
 	struct pci_dev *pcidev = NULL;
+	u32 smmu_mapping[2];
 	int rc;
 	u32 val;
 
@@ -954,8 +990,27 @@
 	ctx->use_smmu = of_property_read_bool(of_node, "qcom,smmu-support");
 	ctx->bus_scale = msm_bus_cl_get_pdata(pdev);
 
-	ctx->smmu_bypass = 1;
-	ctx->smmu_fast_map = 0;
+	ctx->smmu_s1_en = of_property_read_bool(of_node, "qcom,smmu-s1-en");
+	if (ctx->smmu_s1_en) {
+		ctx->smmu_fast_map = of_property_read_bool(
+						of_node, "qcom,smmu-fast-map");
+		ctx->smmu_coherent = of_property_read_bool(
+						of_node, "qcom,smmu-coherent");
+	}
+	rc = of_property_read_u32_array(dev->of_node, "qcom,smmu-mapping",
+			smmu_mapping, 2);
+	if (rc) {
+		dev_err(ctx->dev,
+			"Failed to read base/size smmu addresses %d, fallback to default\n",
+			rc);
+		ctx->smmu_base = SMMU_BASE;
+		ctx->smmu_size = SMMU_SIZE;
+	} else {
+		ctx->smmu_base = smmu_mapping[0];
+		ctx->smmu_size = smmu_mapping[1];
+	}
+	dev_dbg(ctx->dev, "smmu_base=0x%x smmu_sise=0x%x\n",
+		ctx->smmu_base, ctx->smmu_size);
 
 	/*== execute ==*/
 	/* turn device on */
diff --git a/drivers/power/supply/qcom/Kconfig b/drivers/power/supply/qcom/Kconfig
index 79ea712..362375f 100644
--- a/drivers/power/supply/qcom/Kconfig
+++ b/drivers/power/supply/qcom/Kconfig
@@ -20,6 +20,16 @@
 	  The driver reports the charger status via the power supply framework.
 	  A charger status change triggers an IRQ via the device STAT pin.
 
+config SMB1355_SLAVE_CHARGER
+	tristate "SMB1355 Slave Battery Charger"
+	depends on MFD_I2C_PMIC
+	help
+	  Say Y to include support for SMB1355 Battery Charger.
+	  SMB1355 is a single phase 5A battery charger.
+	  The driver supports charger enable/disable.
+	  The driver reports the charger status via the power supply framework.
+	  A charger status change triggers an IRQ via the device STAT pin.
+
 config SMB1351_USB_CHARGER
 	tristate "smb1351 usb charger (with VBUS detection)"
 	depends on I2C
diff --git a/drivers/power/supply/qcom/Makefile b/drivers/power/supply/qcom/Makefile
index 171444f..bc19b24 100644
--- a/drivers/power/supply/qcom/Makefile
+++ b/drivers/power/supply/qcom/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_QPNP_FG_GEN3)     += qpnp-fg-gen3.o fg-memif.o fg-util.o
 obj-$(CONFIG_SMB135X_CHARGER)   += smb135x-charger.o pmic-voter.o
+obj-$(CONFIG_SMB1355_SLAVE_CHARGER)   += smb1355-charger.o pmic-voter.o
 obj-$(CONFIG_SMB1351_USB_CHARGER) += smb1351-charger.o pmic-voter.o battery.o
 obj-$(CONFIG_QPNP_SMB2)		+= qpnp-smb2.o smb-lib.o pmic-voter.o storm-watch.o battery.o
 obj-$(CONFIG_SMB138X_CHARGER)	+= smb138x-charger.o smb-lib.o pmic-voter.o storm-watch.o battery.o
diff --git a/drivers/power/supply/qcom/smb1355-charger.c b/drivers/power/supply/qcom/smb1355-charger.c
new file mode 100644
index 0000000..d5fff74
--- /dev/null
+++ b/drivers/power/supply/qcom/smb1355-charger.c
@@ -0,0 +1,675 @@
+/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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.
+ */
+
+#define pr_fmt(fmt) "SMB1355: %s: " fmt, __func__
+
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/qpnp/qpnp-revid.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/power_supply.h>
+#include <linux/pmic-voter.h>
+
+#define SMB1355_DEFAULT_FCC_UA 1000000
+
+/* SMB1355 registers, different than mentioned in smb-reg.h */
+
+#define CHGR_BASE	0x1000
+#define BATIF_BASE	0x1200
+#define USBIN_BASE	0x1300
+#define MISC_BASE	0x1600
+
+#define BATTERY_STATUS_2_REG			(CHGR_BASE + 0x0B)
+#define DISABLE_CHARGING_BIT			BIT(3)
+
+#define BATTERY_STATUS_3_REG			(CHGR_BASE + 0x0C)
+#define BATT_GT_PRE_TO_FAST_BIT			BIT(4)
+#define ENABLE_CHARGING_BIT			BIT(3)
+
+#define CHGR_CFG2_REG				(CHGR_BASE + 0x51)
+#define CHG_EN_SRC_BIT				BIT(7)
+#define CHG_EN_POLARITY_BIT			BIT(6)
+
+#define CFG_REG					(CHGR_BASE + 0x53)
+#define CHG_OPTION_PIN_TRIM_BIT			BIT(7)
+#define BATN_SNS_CFG_BIT			BIT(4)
+#define CFG_TAPER_DIS_AFVC_BIT			BIT(3)
+#define BATFET_SHUTDOWN_CFG_BIT			BIT(2)
+#define VDISCHG_EN_CFG_BIT			BIT(1)
+#define VCHG_EN_CFG_BIT				BIT(0)
+
+#define FAST_CHARGE_CURRENT_CFG_REG		(CHGR_BASE + 0x61)
+#define FAST_CHARGE_CURRENT_SETTING_MASK	GENMASK(7, 0)
+
+#define CHGR_BATTOV_CFG_REG			(CHGR_BASE + 0x70)
+#define BATTOV_SETTING_MASK			GENMASK(7, 0)
+
+#define BARK_BITE_WDOG_PET_REG			(MISC_BASE + 0x43)
+#define BARK_BITE_WDOG_PET_BIT			BIT(0)
+
+#define WD_CFG_REG				(MISC_BASE + 0x51)
+#define WATCHDOG_TRIGGER_AFP_EN_BIT		BIT(7)
+#define BARK_WDOG_INT_EN_BIT			BIT(6)
+#define BITE_WDOG_INT_EN_BIT			BIT(5)
+#define WDOG_IRQ_SFT_BIT			BIT(2)
+#define WDOG_TIMER_EN_ON_PLUGIN_BIT		BIT(1)
+#define WDOG_TIMER_EN_BIT			BIT(0)
+
+#define SNARL_BARK_BITE_WD_CFG_REG		(MISC_BASE + 0x53)
+#define BITE_WDOG_DISABLE_CHARGING_CFG_BIT	BIT(7)
+#define SNARL_WDOG_TIMEOUT_MASK			GENMASK(6, 4)
+#define BARK_WDOG_TIMEOUT_MASK			GENMASK(3, 2)
+#define BITE_WDOG_TIMEOUT_MASK			GENMASK(1, 0)
+
+struct smb_chg_param {
+	const char	*name;
+	u16		reg;
+	int		min_u;
+	int		max_u;
+	int		step_u;
+};
+
+struct smb_params {
+	struct smb_chg_param	fcc;
+	struct smb_chg_param	ov;
+};
+
+static struct smb_params v1_params = {
+	.fcc		= {
+		.name	= "fast charge current",
+		.reg	= FAST_CHARGE_CURRENT_CFG_REG,
+		.min_u	= 0,
+		.max_u	= 6000000,
+		.step_u	= 25000,
+	},
+	.ov		= {
+		.name	= "battery over voltage",
+		.reg	= CHGR_BATTOV_CFG_REG,
+		.min_u	= 2450000,
+		.max_u	= 5000000,
+		.step_u	= 10000,
+	},
+};
+
+struct smb_irq_info {
+	const char		*name;
+	const irq_handler_t	handler;
+	const bool		wake;
+	int			irq;
+};
+
+struct smb1355 {
+	struct device		*dev;
+	char			*name;
+	struct regmap		*regmap;
+
+	struct smb_params	param;
+
+	struct mutex		write_lock;
+
+	struct power_supply	*parallel_psy;
+	struct pmic_revid_data	*pmic_rev_id;
+};
+
+static bool is_secure(struct smb1355 *chip, int addr)
+{
+	/* assume everything above 0xA0 is secure */
+	return (addr & 0xFF) >= 0xA0;
+}
+
+static int smb1355_read(struct smb1355 *chip, u16 addr, u8 *val)
+{
+	unsigned int temp;
+	int rc;
+
+	rc = regmap_read(chip->regmap, addr, &temp);
+	if (rc >= 0)
+		*val = (u8)temp;
+
+	return rc;
+}
+
+static int smb1355_masked_write(struct smb1355 *chip, u16 addr, u8 mask, u8 val)
+{
+	int rc;
+
+	mutex_lock(&chip->write_lock);
+	if (is_secure(chip, addr)) {
+		rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5);
+		if (rc < 0)
+			goto unlock;
+	}
+
+	rc = regmap_update_bits(chip->regmap, addr, mask, val);
+
+unlock:
+	mutex_unlock(&chip->write_lock);
+	return rc;
+}
+
+static int smb1355_write(struct smb1355 *chip, u16 addr, u8 val)
+{
+	int rc;
+
+	mutex_lock(&chip->write_lock);
+
+	if (is_secure(chip, addr)) {
+		rc = regmap_write(chip->regmap, (addr & ~(0xFF)) | 0xD0, 0xA5);
+		if (rc < 0)
+			goto unlock;
+	}
+
+	rc = regmap_write(chip->regmap, addr, val);
+
+unlock:
+	mutex_unlock(&chip->write_lock);
+	return rc;
+}
+
+static int smb1355_set_charge_param(struct smb1355 *chip,
+			struct smb_chg_param *param, int val_u)
+{
+	int rc;
+	u8 val_raw;
+
+	if (val_u > param->max_u || val_u < param->min_u) {
+		pr_err("%s: %d is out of range [%d, %d]\n",
+			param->name, val_u, param->min_u, param->max_u);
+		return -EINVAL;
+	}
+
+	val_raw = (val_u - param->min_u) / param->step_u;
+
+	rc = smb1355_write(chip, param->reg, val_raw);
+	if (rc < 0) {
+		pr_err("%s: Couldn't write 0x%02x to 0x%04x rc=%d\n",
+			param->name, val_raw, param->reg, rc);
+		return rc;
+	}
+
+	return rc;
+}
+
+static int smb1355_get_charge_param(struct smb1355 *chip,
+			struct smb_chg_param *param, int *val_u)
+{
+	int rc;
+	u8 val_raw;
+
+	rc = smb1355_read(chip, param->reg, &val_raw);
+	if (rc < 0) {
+		pr_err("%s: Couldn't read from 0x%04x rc=%d\n",
+			param->name, param->reg, rc);
+		return rc;
+	}
+
+	*val_u = val_raw * param->step_u + param->min_u;
+
+	return rc;
+}
+
+static irqreturn_t smb1355_handle_chg_state_change(int irq, void *data)
+{
+	struct smb1355 *chip = data;
+
+	if (chip->parallel_psy)
+		power_supply_changed(chip->parallel_psy);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t smb1355_handle_wdog_bark(int irq, void *data)
+{
+	struct smb1355 *chip = data;
+	int rc;
+
+	rc = smb1355_write(chip, BARK_BITE_WDOG_PET_REG,
+					BARK_BITE_WDOG_PET_BIT);
+	if (rc < 0)
+		pr_err("Couldn't pet the dog rc=%d\n", rc);
+
+	return IRQ_HANDLED;
+}
+
+/*****************************
+ * PARALLEL PSY REGISTRATION *
+ *****************************/
+
+static enum power_supply_property smb1355_parallel_props[] = {
+	POWER_SUPPLY_PROP_CHARGE_TYPE,
+	POWER_SUPPLY_PROP_CHARGING_ENABLED,
+	POWER_SUPPLY_PROP_PIN_ENABLED,
+	POWER_SUPPLY_PROP_INPUT_SUSPEND,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX,
+	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+};
+
+static int smb1355_get_prop_batt_charge_type(struct smb1355 *chip,
+				union power_supply_propval *val)
+{
+	int rc;
+	u8 stat;
+
+	rc = smb1355_read(chip, BATTERY_STATUS_3_REG, &stat);
+	if (rc < 0) {
+		pr_err("Couldn't read SMB1355_BATTERY_STATUS_3 rc=%d\n", rc);
+		return rc;
+	}
+
+	if (stat & ENABLE_CHARGING_BIT) {
+		if (stat & BATT_GT_PRE_TO_FAST_BIT)
+			val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+		else
+			val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+	} else {
+		val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+	}
+
+	return rc;
+}
+
+static int smb1355_get_parallel_charging(struct smb1355 *chip, int *disabled)
+{
+	int rc;
+	u8 cfg2;
+
+	rc = smb1355_read(chip, CHGR_CFG2_REG, &cfg2);
+	if (rc < 0) {
+		pr_err("Couldn't read en_cmg_reg rc=%d\n", rc);
+		return rc;
+	}
+
+	if (cfg2 & CHG_EN_SRC_BIT)
+		*disabled = 0;
+	else
+		*disabled = 1;
+
+	return 0;
+}
+
+static int smb1355_parallel_get_prop(struct power_supply *psy,
+				     enum power_supply_property prop,
+				     union power_supply_propval *val)
+{
+	struct smb1355 *chip = power_supply_get_drvdata(psy);
+	u8 stat;
+	int rc = 0;
+
+	switch (prop) {
+	case POWER_SUPPLY_PROP_CHARGE_TYPE:
+		rc = smb1355_get_prop_batt_charge_type(chip, val);
+		break;
+	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+		rc = smb1355_read(chip, BATTERY_STATUS_3_REG, &stat);
+		if (rc >= 0)
+			val->intval = (bool)(stat & ENABLE_CHARGING_BIT);
+		break;
+	case POWER_SUPPLY_PROP_PIN_ENABLED:
+		rc = smb1355_read(chip, BATTERY_STATUS_2_REG, &stat);
+		if (rc >= 0)
+			val->intval = !(stat & DISABLE_CHARGING_BIT);
+		break;
+	case POWER_SUPPLY_PROP_INPUT_SUSPEND:
+		rc = smb1355_get_parallel_charging(chip, &val->intval);
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		rc = smb1355_get_charge_param(chip, &chip->param.ov,
+						&val->intval);
+		break;
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+		rc = smb1355_get_charge_param(chip, &chip->param.fcc,
+						&val->intval);
+		break;
+	case POWER_SUPPLY_PROP_MODEL_NAME:
+		val->strval = chip->name;
+		break;
+	case POWER_SUPPLY_PROP_PARALLEL_MODE:
+		val->intval = POWER_SUPPLY_PL_USBMID_USBMID;
+		break;
+	default:
+		pr_err_ratelimited("parallel psy get prop %d not supported\n",
+			prop);
+		return -EINVAL;
+	}
+
+	if (rc < 0) {
+		pr_debug("Couldn't get prop %d rc = %d\n", prop, rc);
+		return -ENODATA;
+	}
+
+	return rc;
+}
+
+static int smb1355_set_parallel_charging(struct smb1355 *chip, bool disable)
+{
+	int rc;
+
+	rc = smb1355_masked_write(chip, WD_CFG_REG, WDOG_TIMER_EN_BIT,
+				 disable ? 0 : WDOG_TIMER_EN_BIT);
+	if (rc < 0) {
+		pr_err("Couldn't %s watchdog rc=%d\n",
+		       disable ? "disable" : "enable", rc);
+		disable = true;
+	}
+
+	/*
+	 * Configure charge enable for high polarity and
+	 * When disabling charging set it to cmd register control(cmd bit=0)
+	 * When enabling charging set it to pin control
+	 */
+	rc = smb1355_masked_write(chip, CHGR_CFG2_REG,
+			CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT,
+			disable ? 0 : CHG_EN_SRC_BIT);
+	if (rc < 0) {
+		pr_err("Couldn't configure charge enable source rc=%d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int smb1355_parallel_set_prop(struct power_supply *psy,
+				     enum power_supply_property prop,
+				     const union power_supply_propval *val)
+{
+	struct smb1355 *chip = power_supply_get_drvdata(psy);
+	int rc = 0;
+
+	switch (prop) {
+	case POWER_SUPPLY_PROP_INPUT_SUSPEND:
+		rc = smb1355_set_parallel_charging(chip, (bool)val->intval);
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+		rc = smb1355_set_charge_param(chip, &chip->param.ov,
+						val->intval);
+		break;
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+		rc = smb1355_set_charge_param(chip, &chip->param.fcc,
+						val->intval);
+		break;
+	default:
+		pr_debug("parallel power supply set prop %d not supported\n",
+			prop);
+		return -EINVAL;
+	}
+
+	return rc;
+}
+
+static int smb1355_parallel_prop_is_writeable(struct power_supply *psy,
+					      enum power_supply_property prop)
+{
+	return 0;
+}
+
+static struct power_supply_desc parallel_psy_desc = {
+	.name			= "parallel",
+	.type			= POWER_SUPPLY_TYPE_PARALLEL,
+	.properties		= smb1355_parallel_props,
+	.num_properties		= ARRAY_SIZE(smb1355_parallel_props),
+	.get_property		= smb1355_parallel_get_prop,
+	.set_property		= smb1355_parallel_set_prop,
+	.property_is_writeable	= smb1355_parallel_prop_is_writeable,
+};
+
+static int smb1355_init_parallel_psy(struct smb1355 *chip)
+{
+	struct power_supply_config parallel_cfg = {};
+
+	parallel_cfg.drv_data = chip;
+	parallel_cfg.of_node = chip->dev->of_node;
+
+	/* change to smb1355's property list */
+	parallel_psy_desc.properties = smb1355_parallel_props;
+	parallel_psy_desc.num_properties = ARRAY_SIZE(smb1355_parallel_props);
+	chip->parallel_psy = devm_power_supply_register(chip->dev,
+						   &parallel_psy_desc,
+						   &parallel_cfg);
+	if (IS_ERR(chip->parallel_psy)) {
+		pr_err("Couldn't register parallel power supply\n");
+		return PTR_ERR(chip->parallel_psy);
+	}
+
+	return 0;
+}
+
+/***************************
+ * HARDWARE INITIALIZATION *
+ ***************************/
+
+static int smb1355_init_hw(struct smb1355 *chip)
+{
+	int rc;
+
+	/* enable watchdog bark and bite interrupts, and disable the watchdog */
+	rc = smb1355_masked_write(chip, WD_CFG_REG, WDOG_TIMER_EN_BIT
+			| WDOG_TIMER_EN_ON_PLUGIN_BIT | BITE_WDOG_INT_EN_BIT
+			| BARK_WDOG_INT_EN_BIT,
+			BITE_WDOG_INT_EN_BIT | BARK_WDOG_INT_EN_BIT);
+	if (rc < 0) {
+		pr_err("Couldn't configure the watchdog rc=%d\n", rc);
+		return rc;
+	}
+
+	/* disable charging when watchdog bites */
+	rc = smb1355_masked_write(chip, SNARL_BARK_BITE_WD_CFG_REG,
+				 BITE_WDOG_DISABLE_CHARGING_CFG_BIT,
+				 BITE_WDOG_DISABLE_CHARGING_CFG_BIT);
+	if (rc < 0) {
+		pr_err("Couldn't configure the watchdog bite rc=%d\n", rc);
+		return rc;
+	}
+
+	/* disable parallel charging path */
+	rc = smb1355_set_parallel_charging(chip, true);
+	if (rc < 0) {
+		pr_err("Couldn't disable parallel path rc=%d\n", rc);
+		return rc;
+	}
+
+	/* initialize FCC to 0 */
+	rc = smb1355_set_charge_param(chip, &chip->param.fcc, 0);
+	if (rc < 0) {
+		pr_err("Couldn't set 0 FCC rc=%d\n", rc);
+		return rc;
+	}
+
+	/* enable parallel current sensing */
+	rc = smb1355_masked_write(chip, CFG_REG,
+				 VCHG_EN_CFG_BIT, VCHG_EN_CFG_BIT);
+	if (rc < 0) {
+		pr_err("Couldn't enable parallel current sensing rc=%d\n",
+			rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+/**************************
+ * INTERRUPT REGISTRATION *
+ **************************/
+static struct smb_irq_info smb1355_irqs[] = {
+	[0] = {
+		.name		= "wdog-bark",
+		.handler	= smb1355_handle_wdog_bark,
+	},
+	[1] = {
+		.name		= "chg-state-change",
+		.handler	= smb1355_handle_chg_state_change,
+		.wake		= true,
+	},
+};
+
+static int smb1355_get_irq_index_byname(const char *irq_name)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(smb1355_irqs); i++) {
+		if (strcmp(smb1355_irqs[i].name, irq_name) == 0)
+			return i;
+	}
+
+	return -ENOENT;
+}
+
+static int smb1355_request_interrupt(struct smb1355 *chip,
+				struct device_node *node,
+				const char *irq_name)
+{
+	int rc = 0, irq, irq_index;
+
+	irq = of_irq_get_byname(node, irq_name);
+	if (irq < 0) {
+		pr_err("Couldn't get irq %s byname\n", irq_name);
+		return irq;
+	}
+
+	irq_index = smb1355_get_irq_index_byname(irq_name);
+	if (irq_index < 0) {
+		pr_err("%s is not a defined irq\n", irq_name);
+		return irq_index;
+	}
+
+	if (!smb1355_irqs[irq_index].handler)
+		return 0;
+
+	rc = devm_request_threaded_irq(chip->dev, irq, NULL,
+				smb1355_irqs[irq_index].handler,
+				IRQF_ONESHOT, irq_name, chip);
+	if (rc < 0) {
+		pr_err("Couldn't request irq %d rc=%d\n", irq, rc);
+		return rc;
+	}
+
+	if (smb1355_irqs[irq_index].wake)
+		enable_irq_wake(irq);
+
+	return rc;
+}
+
+static int smb1355_request_interrupts(struct smb1355 *chip)
+{
+	struct device_node *node = chip->dev->of_node;
+	struct device_node *child;
+	int rc = 0;
+	const char *name;
+	struct property *prop;
+
+	for_each_available_child_of_node(node, child) {
+		of_property_for_each_string(child, "interrupt-names",
+					prop, name) {
+			rc = smb1355_request_interrupt(chip, child, name);
+			if (rc < 0) {
+				pr_err("Couldn't request interrupt %s rc=%d\n",
+					name, rc);
+				return rc;
+			}
+		}
+	}
+
+	return rc;
+}
+
+/*********
+ * PROBE *
+ *********/
+static const struct of_device_id match_table[] = {
+	{
+		.compatible	= "qcom,smb1355",
+	},
+	{ },
+};
+
+static int smb1355_probe(struct platform_device *pdev)
+{
+	struct smb1355 *chip;
+	const struct of_device_id *id;
+	int rc = 0;
+
+	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	chip->dev = &pdev->dev;
+	chip->param = v1_params;
+	chip->name = "smb1355";
+	mutex_init(&chip->write_lock);
+
+	chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
+	if (!chip->regmap) {
+		pr_err("parent regmap is missing\n");
+		return -EINVAL;
+	}
+
+	id = of_match_device(of_match_ptr(match_table), chip->dev);
+	if (!id) {
+		pr_err("Couldn't find a matching device\n");
+		return -ENODEV;
+	}
+
+	platform_set_drvdata(pdev, chip);
+
+	rc = smb1355_init_hw(chip);
+	if (rc < 0) {
+		pr_err("Couldn't initialize hardware rc=%d\n", rc);
+		goto cleanup;
+	}
+
+	rc = smb1355_init_parallel_psy(chip);
+	if (rc < 0) {
+		pr_err("Couldn't initialize parallel psy rc=%d\n", rc);
+		goto cleanup;
+	}
+
+	rc = smb1355_request_interrupts(chip);
+	if (rc < 0) {
+		pr_err("Couldn't request interrupts rc=%d\n", rc);
+		goto cleanup;
+	}
+
+	pr_info("%s probed successfully\n", chip->name);
+	return rc;
+
+cleanup:
+	platform_set_drvdata(pdev, NULL);
+	return rc;
+}
+
+static int smb1355_remove(struct platform_device *pdev)
+{
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver smb1355_driver = {
+	.driver	= {
+		.name		= "qcom,smb1355-charger",
+		.owner		= THIS_MODULE,
+		.of_match_table	= match_table,
+	},
+	.probe	= smb1355_probe,
+	.remove	= smb1355_remove,
+};
+module_platform_driver(smb1355_driver);
+
+MODULE_DESCRIPTION("QPNP SMB1355 Charger Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/qdsp6v2/Makefile b/drivers/soc/qcom/qdsp6v2/Makefile
index 8c5b0d0..b2cf03c 100644
--- a/drivers/soc/qcom/qdsp6v2/Makefile
+++ b/drivers/soc/qcom/qdsp6v2/Makefile
@@ -1,7 +1,7 @@
-obj-$(CONFIG_MSM_QDSP6_APRV2) += apr.o apr_v2.o apr_tal.o voice_svc.o
-obj-$(CONFIG_MSM_QDSP6_APRV3) += apr.o apr_v3.o apr_tal.o voice_svc.o
-obj-$(CONFIG_MSM_QDSP6_APRV2_GLINK) += apr.o apr_v2.o apr_tal_glink.o voice_svc.o
-obj-$(CONFIG_MSM_QDSP6_APRV3_GLINK) += apr.o apr_v3.o apr_tal_glink.o voice_svc.o
+obj-$(CONFIG_MSM_QDSP6_APRV2) += apr.o apr_v2.o apr_tal.o
+obj-$(CONFIG_MSM_QDSP6_APRV3) += apr.o apr_v3.o apr_tal.o
+obj-$(CONFIG_MSM_QDSP6_APRV2_GLINK) += apr.o apr_v2.o apr_tal_glink.o
+obj-$(CONFIG_MSM_QDSP6_APRV3_GLINK) += apr.o apr_v3.o apr_tal_glink.o
 obj-$(CONFIG_SND_SOC_MSM_QDSP6V2_INTF) += msm_audio_ion.o
 obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
 obj-$(CONFIG_MSM_QDSP6_SSR) += audio_ssr.o
diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c
deleted file mode 100644
index f3b1b83..0000000
--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c
+++ /dev/null
@@ -1,837 +0,0 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/cdev.h>
-#include <linux/qdsp6v2/apr_tal.h>
-#include <linux/qdsp6v2/apr.h>
-#include <sound/voice_svc.h>
-
-#define MINOR_NUMBER 1
-#define APR_MAX_RESPONSE 10
-#define TIMEOUT_MS 1000
-
-#define MAX(a, b) ((a) >= (b) ? (a) : (b))
-
-struct voice_svc_device {
-	struct cdev *cdev;
-	struct device *dev;
-	int major;
-};
-
-struct voice_svc_prvt {
-	void *apr_q6_mvm;
-	void *apr_q6_cvs;
-	uint16_t response_count;
-	struct list_head response_queue;
-	wait_queue_head_t response_wait;
-	spinlock_t response_lock;
-	/*
-	 * This mutex ensures responses are processed in sequential order and
-	 * that no two threads access and free the same response at the same
-	 * time.
-	 */
-	struct mutex response_mutex_lock;
-};
-
-struct apr_data {
-	struct apr_hdr hdr;
-	__u8 payload[0];
-} __packed;
-
-struct apr_response_list {
-	struct list_head list;
-	struct voice_svc_cmd_response resp;
-};
-
-static struct voice_svc_device *voice_svc_dev;
-static struct class *voice_svc_class;
-static bool reg_dummy_sess;
-static void *dummy_q6_mvm;
-static void *dummy_q6_cvs;
-dev_t device_num;
-
-static int voice_svc_dummy_reg(void);
-static int32_t qdsp_dummy_apr_callback(struct apr_client_data *data,
-					void *priv);
-
-static int32_t qdsp_apr_callback(struct apr_client_data *data, void *priv)
-{
-	struct voice_svc_prvt *prtd;
-	struct apr_response_list *response_list;
-	unsigned long spin_flags;
-
-	if ((data == NULL) || (priv == NULL)) {
-		pr_err("%s: data or priv is NULL\n", __func__);
-
-		return -EINVAL;
-	}
-
-	prtd = (struct voice_svc_prvt *)priv;
-	if (prtd == NULL) {
-		pr_err("%s: private data is NULL\n", __func__);
-
-		return -EINVAL;
-	}
-
-	pr_debug("%s: data->opcode %x\n", __func__,
-		 data->opcode);
-
-	if (data->opcode == RESET_EVENTS) {
-		if (data->reset_proc == APR_DEST_QDSP6) {
-			pr_debug("%s: Received ADSP reset event\n", __func__);
-
-			if (prtd->apr_q6_mvm != NULL) {
-				apr_reset(prtd->apr_q6_mvm);
-				prtd->apr_q6_mvm = NULL;
-			}
-
-			if (prtd->apr_q6_cvs != NULL) {
-				apr_reset(prtd->apr_q6_cvs);
-				prtd->apr_q6_cvs = NULL;
-			}
-		} else if (data->reset_proc == APR_DEST_MODEM) {
-			pr_debug("%s: Received Modem reset event\n", __func__);
-		}
-		/* Set the remaining member variables to default values
-		 * for RESET_EVENTS
-		 */
-		data->payload_size = 0;
-		data->payload = NULL;
-		data->src_port = 0;
-		data->dest_port = 0;
-		data->token = 0;
-	}
-
-	spin_lock_irqsave(&prtd->response_lock, spin_flags);
-
-	if (prtd->response_count < APR_MAX_RESPONSE) {
-		response_list = kmalloc(sizeof(struct apr_response_list) +
-					data->payload_size, GFP_ATOMIC);
-		if (response_list == NULL) {
-			spin_unlock_irqrestore(&prtd->response_lock,
-					       spin_flags);
-			return -ENOMEM;
-		}
-
-		response_list->resp.src_port = data->src_port;
-
-		/* Reverting the bit manipulation done in voice_svc_update_hdr
-		 * to the src_port which is returned to us as dest_port.
-		 */
-		response_list->resp.dest_port = ((data->dest_port) >> 8);
-		response_list->resp.token = data->token;
-		response_list->resp.opcode = data->opcode;
-		response_list->resp.payload_size = data->payload_size;
-		if (data->payload != NULL && data->payload_size > 0) {
-			memcpy(response_list->resp.payload, data->payload,
-			       data->payload_size);
-		}
-
-		list_add_tail(&response_list->list, &prtd->response_queue);
-		prtd->response_count++;
-		spin_unlock_irqrestore(&prtd->response_lock, spin_flags);
-
-		wake_up(&prtd->response_wait);
-	} else {
-		spin_unlock_irqrestore(&prtd->response_lock, spin_flags);
-		pr_err("%s: Response dropped since the queue is full\n",
-		       __func__);
-	}
-
-	return 0;
-}
-
-static int32_t qdsp_dummy_apr_callback(struct apr_client_data *data, void *priv)
-{
-	/* Do Nothing */
-	return 0;
-}
-
-static void voice_svc_update_hdr(struct voice_svc_cmd_request *apr_req_data,
-				 struct apr_data *aprdata)
-{
-
-	aprdata->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-				       APR_HDR_LEN(sizeof(struct apr_hdr)),
-				       APR_PKT_VER);
-	/* Bit manipulation is done on src_port so that a unique ID is sent.
-	 * This manipulation can be used in the future where the same service
-	 * is tried to open multiple times with the same src_port. At that
-	 * time 0x0001 can be replaced with other values depending on the
-	 * count.
-	 */
-	aprdata->hdr.src_port = ((apr_req_data->src_port) << 8 | 0x0001);
-	aprdata->hdr.dest_port = apr_req_data->dest_port;
-	aprdata->hdr.token = apr_req_data->token;
-	aprdata->hdr.opcode = apr_req_data->opcode;
-	aprdata->hdr.pkt_size  = APR_PKT_SIZE(APR_HDR_SIZE,
-					apr_req_data->payload_size);
-	memcpy(aprdata->payload, apr_req_data->payload,
-	       apr_req_data->payload_size);
-}
-
-static int voice_svc_send_req(struct voice_svc_cmd_request *apr_request,
-			      struct voice_svc_prvt *prtd)
-{
-	int ret = 0;
-	void *apr_handle = NULL;
-	struct apr_data *aprdata = NULL;
-	uint32_t user_payload_size;
-	uint32_t payload_size;
-
-	pr_debug("%s\n", __func__);
-
-	if (apr_request == NULL) {
-		pr_err("%s: apr_request is NULL\n", __func__);
-
-		ret = -EINVAL;
-		goto done;
-	}
-
-	user_payload_size = apr_request->payload_size;
-	payload_size = sizeof(struct apr_data) + user_payload_size;
-
-	if (payload_size <= user_payload_size) {
-		pr_err("%s: invalid payload size ( 0x%x ).\n",
-			__func__, user_payload_size);
-		ret = -EINVAL;
-		goto done;
-	} else {
-		aprdata = kmalloc(payload_size, GFP_KERNEL);
-		if (aprdata == NULL) {
-			ret = -ENOMEM;
-			goto done;
-		}
-	}
-
-	voice_svc_update_hdr(apr_request, aprdata);
-
-	if (!strcmp(apr_request->svc_name, VOICE_SVC_CVS_STR)) {
-		apr_handle = prtd->apr_q6_cvs;
-	} else if (!strcmp(apr_request->svc_name, VOICE_SVC_MVM_STR)) {
-		apr_handle = prtd->apr_q6_mvm;
-	} else {
-		pr_err("%s: Invalid service %.*s\n", __func__,
-			MAX_APR_SERVICE_NAME_LEN, apr_request->svc_name);
-
-		ret = -EINVAL;
-		goto done;
-	}
-
-	ret = apr_send_pkt(apr_handle, (uint32_t *)aprdata);
-
-	if (ret < 0) {
-		pr_err("%s: Fail in sending request %d\n",
-			__func__, ret);
-		ret = -EINVAL;
-	} else {
-		pr_debug("%s: apr packet sent successfully %d\n",
-			 __func__, ret);
-		ret = 0;
-	}
-
-done:
-	kfree(aprdata);
-	return ret;
-}
-static int voice_svc_reg(char *svc, uint32_t src_port,
-			 struct voice_svc_prvt *prtd, void **handle)
-{
-	int ret = 0;
-
-	pr_debug("%s\n", __func__);
-
-	if (handle == NULL) {
-		pr_err("%s: handle is NULL\n", __func__);
-		ret = -EINVAL;
-		goto done;
-	}
-
-	if (*handle != NULL) {
-		pr_err("%s: svc handle not NULL\n", __func__);
-		ret = -EINVAL;
-		goto done;
-	}
-
-	if (src_port == (APR_MAX_PORTS - 1)) {
-		pr_err("%s: SRC port reserved for dummy session\n", __func__);
-		pr_err("%s: Unable to register %s\n", __func__, svc);
-		ret = -EINVAL;
-		goto done;
-	}
-
-	*handle = apr_register("ADSP",
-			       svc, qdsp_apr_callback,
-			       ((src_port) << 8 | 0x0001),
-			       prtd);
-
-	if (*handle == NULL) {
-		pr_err("%s: Unable to register %s\n",
-		       __func__, svc);
-
-		ret = -EFAULT;
-		goto done;
-	}
-	pr_debug("%s: Register %s successful\n",
-		__func__, svc);
-done:
-	return ret;
-}
-
-static int voice_svc_dereg(char *svc, void **handle)
-{
-	int ret = 0;
-
-	pr_debug("%s\n", __func__);
-
-	if (handle == NULL) {
-		pr_err("%s: handle is NULL\n", __func__);
-		ret = -EINVAL;
-		goto done;
-	}
-
-	if (*handle == NULL) {
-		pr_err("%s: svc handle is NULL\n", __func__);
-		ret = -EINVAL;
-		goto done;
-	}
-
-	ret = apr_deregister(*handle);
-	if (ret) {
-		pr_err("%s: Unable to deregister service %s; error: %d\n",
-		       __func__, svc, ret);
-
-		goto done;
-	}
-	*handle = NULL;
-	pr_debug("%s: deregister %s successful\n", __func__, svc);
-
-done:
-	return ret;
-}
-
-static int process_reg_cmd(struct voice_svc_register *apr_reg_svc,
-			   struct voice_svc_prvt *prtd)
-{
-	int ret = 0;
-	char *svc = NULL;
-	void **handle = NULL;
-
-	pr_debug("%s\n", __func__);
-
-	if (!strcmp(apr_reg_svc->svc_name, VOICE_SVC_MVM_STR)) {
-		svc = VOICE_SVC_MVM_STR;
-		handle = &prtd->apr_q6_mvm;
-	} else if (!strcmp(apr_reg_svc->svc_name, VOICE_SVC_CVS_STR)) {
-		svc = VOICE_SVC_CVS_STR;
-		handle = &prtd->apr_q6_cvs;
-	} else {
-		pr_err("%s: Invalid Service: %.*s\n", __func__,
-			MAX_APR_SERVICE_NAME_LEN, apr_reg_svc->svc_name);
-		ret = -EINVAL;
-		goto done;
-	}
-
-	if (apr_reg_svc->reg_flag) {
-		ret = voice_svc_reg(svc, apr_reg_svc->src_port, prtd,
-				    handle);
-	} else if (!apr_reg_svc->reg_flag) {
-		ret = voice_svc_dereg(svc, handle);
-	}
-
-done:
-	return ret;
-}
-
-static ssize_t voice_svc_write(struct file *file, const char __user *buf,
-			       size_t count, loff_t *ppos)
-{
-	int ret = 0;
-	struct voice_svc_prvt *prtd;
-	struct voice_svc_write_msg *data = NULL;
-	uint32_t cmd;
-	struct voice_svc_register *register_data = NULL;
-	struct voice_svc_cmd_request *request_data = NULL;
-	uint32_t request_payload_size;
-
-	pr_debug("%s\n", __func__);
-
-	/*
-	 * Check if enough memory is allocated to parse the message type.
-	 * Will check there is enough to hold the payload later.
-	 */
-	if (count >= sizeof(struct voice_svc_write_msg)) {
-		data = kmalloc(count, GFP_KERNEL);
-	} else {
-		pr_debug("%s: invalid data size\n", __func__);
-		ret = -EINVAL;
-		goto done;
-	}
-
-	if (data == NULL) {
-		pr_err("%s: data kmalloc failed.\n", __func__);
-
-		ret = -ENOMEM;
-		goto done;
-	}
-
-	ret = copy_from_user(data, buf, count);
-	if (ret) {
-		pr_err("%s: copy_from_user failed %d\n", __func__, ret);
-
-		ret = -EPERM;
-		goto done;
-	}
-
-	cmd = data->msg_type;
-	prtd = (struct voice_svc_prvt *) file->private_data;
-	if (prtd == NULL) {
-		pr_err("%s: prtd is NULL\n", __func__);
-
-		ret = -EINVAL;
-		goto done;
-	}
-
-	switch (cmd) {
-	case MSG_REGISTER:
-		/*
-		 * Check that count reflects the expected size to ensure
-		 * sufficient memory was allocated. Since voice_svc_register
-		 * has a static size, this should be exact.
-		 */
-		if (count == (sizeof(struct voice_svc_write_msg) +
-			      sizeof(struct voice_svc_register))) {
-			register_data =
-				(struct voice_svc_register *)data->payload;
-			if (register_data == NULL) {
-				pr_err("%s: register data is NULL", __func__);
-				ret = -EINVAL;
-				goto done;
-			}
-			ret = process_reg_cmd(register_data, prtd);
-			if (!ret)
-				ret = count;
-		} else {
-			pr_err("%s: invalid data payload size for register command\n",
-				__func__);
-			ret = -EINVAL;
-			goto done;
-		}
-		break;
-	case MSG_REQUEST:
-		/*
-		 * Check that count reflects the expected size to ensure
-		 * sufficient memory was allocated. Since voice_svc_cmd_request
-		 * has a variable size, check the minimum value count must be to
-		 * parse the message request then check the minimum size to hold
-		 * the payload of the message request.
-		 */
-		if (count >= (sizeof(struct voice_svc_write_msg) +
-			      sizeof(struct voice_svc_cmd_request))) {
-			request_data =
-				(struct voice_svc_cmd_request *)data->payload;
-			if (request_data == NULL) {
-				pr_err("%s: request data is NULL", __func__);
-				ret = -EINVAL;
-				goto done;
-			}
-
-			request_payload_size = request_data->payload_size;
-
-			if (count >= (sizeof(struct voice_svc_write_msg) +
-				      sizeof(struct voice_svc_cmd_request) +
-				      request_payload_size)) {
-				ret = voice_svc_send_req(request_data, prtd);
-				if (!ret)
-					ret = count;
-			} else {
-				pr_err("%s: invalid request payload size\n",
-					__func__);
-				ret = -EINVAL;
-				goto done;
-			}
-		} else {
-			pr_err("%s: invalid data payload size for request command\n",
-				__func__);
-			ret = -EINVAL;
-			goto done;
-		}
-		break;
-	default:
-		pr_debug("%s: Invalid command: %u\n", __func__, cmd);
-		ret = -EINVAL;
-	}
-
-done:
-	kfree(data);
-	return ret;
-}
-
-static ssize_t voice_svc_read(struct file *file, char __user *arg,
-			      size_t count, loff_t *ppos)
-{
-	int ret = 0;
-	struct voice_svc_prvt *prtd;
-	struct apr_response_list *resp;
-	unsigned long spin_flags;
-	int size;
-
-	pr_debug("%s\n", __func__);
-
-	prtd = (struct voice_svc_prvt *)file->private_data;
-	if (prtd == NULL) {
-		pr_err("%s: prtd is NULL\n", __func__);
-
-		ret = -EINVAL;
-		goto done;
-	}
-
-	mutex_lock(&prtd->response_mutex_lock);
-	spin_lock_irqsave(&prtd->response_lock, spin_flags);
-
-	if (list_empty(&prtd->response_queue)) {
-		spin_unlock_irqrestore(&prtd->response_lock, spin_flags);
-		pr_debug("%s: wait for a response\n", __func__);
-
-		ret = wait_event_interruptible_timeout(prtd->response_wait,
-					!list_empty(&prtd->response_queue),
-					msecs_to_jiffies(TIMEOUT_MS));
-		if (ret == 0) {
-			pr_debug("%s: Read timeout\n", __func__);
-
-			ret = -ETIMEDOUT;
-			goto unlock;
-		} else if (ret > 0 && !list_empty(&prtd->response_queue)) {
-			pr_debug("%s: Interrupt received for response\n",
-				 __func__);
-		} else if (ret < 0) {
-			pr_debug("%s: Interrupted by SIGNAL %d\n",
-				 __func__, ret);
-
-			goto unlock;
-		}
-
-		spin_lock_irqsave(&prtd->response_lock, spin_flags);
-	}
-
-	resp = list_first_entry(&prtd->response_queue,
-				struct apr_response_list, list);
-
-	spin_unlock_irqrestore(&prtd->response_lock, spin_flags);
-
-	size = resp->resp.payload_size +
-	       sizeof(struct voice_svc_cmd_response);
-
-	if (count < size) {
-		pr_err("%s: Invalid payload size %zd, %d\n",
-		       __func__, count, size);
-
-		ret = -ENOMEM;
-		goto unlock;
-	}
-
-	if (!access_ok(VERIFY_WRITE, arg, size)) {
-		pr_err("%s: Access denied to write\n",
-		       __func__);
-
-		ret = -EPERM;
-		goto unlock;
-	}
-
-	ret = copy_to_user(arg, &resp->resp,
-			 sizeof(struct voice_svc_cmd_response) +
-			 resp->resp.payload_size);
-	if (ret) {
-		pr_err("%s: copy_to_user failed %d\n", __func__, ret);
-
-		ret = -EPERM;
-		goto unlock;
-	}
-
-	spin_lock_irqsave(&prtd->response_lock, spin_flags);
-
-	list_del(&resp->list);
-	prtd->response_count--;
-	kfree(resp);
-
-	spin_unlock_irqrestore(&prtd->response_lock,
-				spin_flags);
-
-	ret = count;
-
-unlock:
-	mutex_unlock(&prtd->response_mutex_lock);
-done:
-	return ret;
-}
-
-static int voice_svc_dummy_reg(void)
-{
-	uint32_t src_port = APR_MAX_PORTS - 1;
-
-	pr_debug("%s\n", __func__);
-	dummy_q6_mvm = apr_register("ADSP", "MVM",
-				qdsp_dummy_apr_callback,
-				src_port,
-				NULL);
-	if (dummy_q6_mvm == NULL) {
-		pr_err("%s: Unable to register dummy MVM\n", __func__);
-		goto err;
-	}
-
-	dummy_q6_cvs = apr_register("ADSP", "CVS",
-				qdsp_dummy_apr_callback,
-				src_port,
-				NULL);
-	if (dummy_q6_cvs == NULL) {
-		pr_err("%s: Unable to register dummy CVS\n", __func__);
-		goto err;
-	}
-	return 0;
-err:
-	if (dummy_q6_mvm != NULL) {
-		apr_deregister(dummy_q6_mvm);
-		dummy_q6_mvm = NULL;
-	}
-	return -EINVAL;
-}
-
-static int voice_svc_open(struct inode *inode, struct file *file)
-{
-	struct voice_svc_prvt *prtd = NULL;
-
-	pr_debug("%s\n", __func__);
-
-	prtd = kmalloc(sizeof(struct voice_svc_prvt), GFP_KERNEL);
-
-	if (prtd == NULL)
-		return -ENOMEM;
-
-	memset(prtd, 0, sizeof(struct voice_svc_prvt));
-	prtd->apr_q6_cvs = NULL;
-	prtd->apr_q6_mvm = NULL;
-	prtd->response_count = 0;
-	INIT_LIST_HEAD(&prtd->response_queue);
-	init_waitqueue_head(&prtd->response_wait);
-	spin_lock_init(&prtd->response_lock);
-	mutex_init(&prtd->response_mutex_lock);
-	file->private_data = (void *)prtd;
-
-	/* Current APR implementation doesn't support session based
-	 * multiple service registrations. The apr_deregister()
-	 * function sets the destination and client IDs to zero, if
-	 * deregister is called for a single service instance.
-	 * To avoid this, register for additional services.
-	 */
-	if (!reg_dummy_sess) {
-		voice_svc_dummy_reg();
-		reg_dummy_sess = 1;
-	}
-	return 0;
-}
-
-static int voice_svc_release(struct inode *inode, struct file *file)
-{
-	int ret = 0;
-	struct apr_response_list *resp = NULL;
-	unsigned long spin_flags;
-	struct voice_svc_prvt *prtd = NULL;
-	char *svc_name = NULL;
-	void **handle = NULL;
-
-	pr_debug("%s\n", __func__);
-
-	prtd = (struct voice_svc_prvt *)file->private_data;
-	if (prtd == NULL) {
-		pr_err("%s: prtd is NULL\n", __func__);
-
-		ret = -EINVAL;
-		goto done;
-	}
-
-	if (prtd->apr_q6_cvs != NULL) {
-		svc_name = VOICE_SVC_MVM_STR;
-		handle = &prtd->apr_q6_cvs;
-		ret = voice_svc_dereg(svc_name, handle);
-		if (ret)
-			pr_err("%s: Failed to dereg CVS %d\n", __func__, ret);
-	}
-
-	if (prtd->apr_q6_mvm != NULL) {
-		svc_name = VOICE_SVC_MVM_STR;
-		handle = &prtd->apr_q6_mvm;
-		ret = voice_svc_dereg(svc_name, handle);
-		if (ret)
-			pr_err("%s: Failed to dereg MVM %d\n", __func__, ret);
-	}
-
-	mutex_lock(&prtd->response_mutex_lock);
-	spin_lock_irqsave(&prtd->response_lock, spin_flags);
-
-	while (!list_empty(&prtd->response_queue)) {
-		pr_debug("%s: Remove item from response queue\n", __func__);
-
-		resp = list_first_entry(&prtd->response_queue,
-					struct apr_response_list, list);
-		list_del(&resp->list);
-		prtd->response_count--;
-		kfree(resp);
-	}
-
-	spin_unlock_irqrestore(&prtd->response_lock, spin_flags);
-	mutex_unlock(&prtd->response_mutex_lock);
-
-	mutex_destroy(&prtd->response_mutex_lock);
-
-	kfree(file->private_data);
-	file->private_data = NULL;
-
-done:
-	return ret;
-}
-
-static const struct file_operations voice_svc_fops = {
-	.owner =                THIS_MODULE,
-	.open =                 voice_svc_open,
-	.read =                 voice_svc_read,
-	.write =                voice_svc_write,
-	.release =              voice_svc_release,
-};
-
-
-static int voice_svc_probe(struct platform_device *pdev)
-{
-	int ret = 0;
-
-	pr_debug("%s\n", __func__);
-
-	voice_svc_dev = devm_kzalloc(&pdev->dev,
-				  sizeof(struct voice_svc_device), GFP_KERNEL);
-	if (!voice_svc_dev) {
-		ret = -ENOMEM;
-		goto done;
-	}
-
-	ret = alloc_chrdev_region(&device_num, 0, MINOR_NUMBER,
-				  VOICE_SVC_DRIVER_NAME);
-	if (ret) {
-		pr_err("%s: Failed to alloc chrdev\n", __func__);
-		ret = -ENODEV;
-		goto chrdev_err;
-	}
-
-	voice_svc_dev->major = MAJOR(device_num);
-	voice_svc_class = class_create(THIS_MODULE, VOICE_SVC_DRIVER_NAME);
-	if (IS_ERR(voice_svc_class)) {
-		ret = PTR_ERR(voice_svc_class);
-		pr_err("%s: Failed to create class; err = %d\n", __func__,
-			ret);
-		goto class_err;
-	}
-
-	voice_svc_dev->dev = device_create(voice_svc_class, NULL, device_num,
-					   NULL, VOICE_SVC_DRIVER_NAME);
-	if (IS_ERR(voice_svc_dev->dev)) {
-		ret = PTR_ERR(voice_svc_dev->dev);
-		pr_err("%s: Failed to create device; err = %d\n", __func__,
-			ret);
-		goto dev_err;
-	}
-
-	voice_svc_dev->cdev = cdev_alloc();
-	if (!voice_svc_dev->cdev) {
-		pr_err("%s: Failed to alloc cdev\n", __func__);
-		ret = -ENOMEM;
-		goto cdev_alloc_err;
-	}
-
-	cdev_init(voice_svc_dev->cdev, &voice_svc_fops);
-	ret = cdev_add(voice_svc_dev->cdev, device_num, MINOR_NUMBER);
-	if (ret) {
-		pr_err("%s: Failed to register chrdev; err = %d\n", __func__,
-			ret);
-		goto add_err;
-	}
-	pr_debug("%s: Device created\n", __func__);
-	goto done;
-
-add_err:
-	cdev_del(voice_svc_dev->cdev);
-cdev_alloc_err:
-	device_destroy(voice_svc_class, device_num);
-dev_err:
-	class_destroy(voice_svc_class);
-class_err:
-	unregister_chrdev_region(0, MINOR_NUMBER);
-chrdev_err:
-	kfree(voice_svc_dev);
-done:
-	return ret;
-}
-
-static int voice_svc_remove(struct platform_device *pdev)
-{
-	pr_debug("%s\n", __func__);
-
-	cdev_del(voice_svc_dev->cdev);
-	kfree(voice_svc_dev->cdev);
-	device_destroy(voice_svc_class, device_num);
-	class_destroy(voice_svc_class);
-	unregister_chrdev_region(0, MINOR_NUMBER);
-	kfree(voice_svc_dev);
-
-	return 0;
-}
-
-static const struct of_device_id voice_svc_of_match[] = {
-	{.compatible = "qcom,msm-voice-svc"},
-	{ }
-};
-MODULE_DEVICE_TABLE(of, voice_svc_of_match);
-
-static struct platform_driver voice_svc_driver = {
-	.probe          = voice_svc_probe,
-	.remove         = voice_svc_remove,
-	.driver         = {
-		.name   = "msm-voice-svc",
-		.owner  = THIS_MODULE,
-		.of_match_table = voice_svc_of_match,
-	},
-};
-
-static int __init voice_svc_init(void)
-{
-	pr_debug("%s\n", __func__);
-
-	return platform_driver_register(&voice_svc_driver);
-}
-
-static void __exit voice_svc_exit(void)
-{
-	pr_debug("%s\n", __func__);
-
-	platform_driver_unregister(&voice_svc_driver);
-}
-
-module_init(voice_svc_init);
-module_exit(voice_svc_exit);
-
-MODULE_DESCRIPTION("Soc QDSP6v2 Voice Service driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index e30c159..b9070bd 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/atomic.h>
+#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -70,6 +71,7 @@
 	struct rpmh_msg *msg_pool;
 	DECLARE_BITMAP(fast_req, RPMH_MAX_FAST_RES);
 	bool dirty;
+	bool in_solver_mode;
 };
 
 struct rpmh_client {
@@ -458,10 +460,21 @@
 	int count = 0;
 	int ret, i, j, k;
 	bool complete_set;
+	unsigned long flags;
+	struct rpmh_mbox *rpm;
 
 	if (rpmh_standalone)
 		return 0;
 
+	/* Do not allow setting wake votes when in solver mode */
+	rpm = rc->rpmh;
+	spin_lock_irqsave(&rpm->lock, flags);
+	if (rpm->in_solver_mode && state == RPMH_WAKE_ONLY_STATE) {
+		spin_unlock_irqrestore(&rpm->lock, flags);
+		return -EIO;
+	}
+	spin_unlock_irqrestore(&rpm->lock, flags);
+
 	while (n[count++])
 		;
 	count--;
@@ -526,6 +539,43 @@
 EXPORT_SYMBOL(rpmh_write_passthru);
 
 /**
+ * rpmh_mode_solver_set: Indicate that the RSC controller hardware has
+ * been configured to be in solver mode
+ *
+ * @rc: The RPMH handle
+ * @enable: Boolean value indicating if the controller is in solver mode.
+ *
+ * When solver mode is enabled, passthru API will not be able to send wake
+ * votes, just awake and active votes.
+ */
+int rpmh_mode_solver_set(struct rpmh_client *rc, bool enable)
+{
+	struct rpmh_mbox *rpm;
+	unsigned long flags;
+
+	if (IS_ERR_OR_NULL(rc))
+		return -EINVAL;
+
+	if (rpmh_standalone)
+		return 0;
+
+	rpm = rc->rpmh;
+	do {
+		spin_lock_irqsave(&rpm->lock, flags);
+		if (mbox_controller_is_idle(rc->chan)) {
+			rpm->in_solver_mode = enable;
+			spin_unlock_irqrestore(&rpm->lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&rpm->lock, flags);
+		udelay(10);
+	} while (1);
+
+	return 0;
+}
+EXPORT_SYMBOL(rpmh_mode_solver_set);
+
+/**
  * rpmh_write_control: Write async control commands to the controller
  *
  * @rc: The RPMh handle got from rpmh_get_dev_channel
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 37125c0..7da9211 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -909,13 +909,11 @@
 	struct cpufreq_cooling_device *cpufreq_dev;
 	char dev_name[THERMAL_NAME_LENGTH];
 	struct cpufreq_frequency_table *pos, *table;
-	struct cpumask temp_mask;
 	unsigned int freq, i, num_cpus;
 	int ret;
 	struct thermal_cooling_device_ops *cooling_ops;
 
-	cpumask_and(&temp_mask, clip_cpus, cpu_online_mask);
-	policy = cpufreq_cpu_get(cpumask_first(&temp_mask));
+	policy = cpufreq_cpu_get(cpumask_first(clip_cpus));
 	if (!policy) {
 		pr_debug("%s: CPUFreq policy not found\n", __func__);
 		return ERR_PTR(-EPROBE_DEFER);
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index da1a0e6..6a3f2ac 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/console.h>
 #include <linux/io.h>
+#include <linux/ipc_logging.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -41,7 +42,7 @@
 #define SE_UART_RX_STALE_CNT		(0x294)
 #define SE_UART_TX_PARITY_CFG		(0x2A4)
 #define SE_UART_RX_PARITY_CFG		(0x2A8)
-#define SE_UART_MANUAL_RFT		(0x2AC)
+#define SE_UART_MANUAL_RFR		(0x2AC)
 
 /* SE_UART_LOOPBACK_CFG */
 #define NO_LOOPBACK		(0)
@@ -84,6 +85,11 @@
 #define PAR_SPACE		(0x10)
 #define PAR_MARK		(0x11)
 
+/* SE_UART_MANUAL_RFR register fields */
+#define UART_MANUAL_RFR_EN	(BIT(31))
+#define UART_RFR_NOT_READY	(BIT(1))
+#define UART_RFR_READY		(BIT(0))
+
 /* UART M_CMD OP codes */
 #define UART_START_TX		(0x1)
 #define UART_START_BREAK	(0x4)
@@ -96,6 +102,7 @@
 #define STALE_TIMEOUT		(16)
 #define DEFAULT_BITS_PER_CHAR	(10)
 #define GENI_UART_NR_PORTS	(15)
+#define GENI_UART_CONS_PORTS	(1)
 #define DEF_FIFO_DEPTH_WORDS	(16)
 #define DEF_TX_WM		(2)
 #define DEF_FIFO_WIDTH_BITS	(32)
@@ -103,6 +110,16 @@
 #define DEFAULT_SE_CLK		(19200000)
 #define DEFAULT_BUS_WIDTH	(4)
 
+#define WAKEBYTE_TIMEOUT_MSEC	(2000)
+#define IPC_LOG_PWR_PAGES	(2)
+#define IPC_LOG_MISC_PAGES	(2)
+#define IPC_LOG_TX_RX_PAGES	(3)
+#define DATA_BYTES_PER_LINE	(32)
+
+#define IPC_LOG_MSG(ctx, x...) do { \
+	if (ctx) \
+		ipc_log_string(ctx, x); \
+} while (0)
 
 struct msm_geni_serial_port {
 	struct uart_port uport;
@@ -123,6 +140,14 @@
 			unsigned int rx_last);
 	struct se_geni_rsc serial_rsc;
 	int loopback;
+	int wakeup_irq;
+	unsigned char wakeup_byte;
+	struct wakeup_source geni_wake;
+	void *ipc_log_tx;
+	void *ipc_log_rx;
+	void *ipc_log_pwr;
+	void *ipc_log_misc;
+	unsigned int cur_baud;
 };
 
 static const struct uart_ops msm_geni_serial_pops;
@@ -137,12 +162,15 @@
 			unsigned int rx_last_byte_valid,
 			unsigned int rx_last);
 static unsigned int msm_geni_serial_tx_empty(struct uart_port *port);
+static int msm_geni_serial_power_on(struct uart_port *uport);
+static void msm_geni_serial_power_off(struct uart_port *uport);
 
 static atomic_t uart_line_id = ATOMIC_INIT(0);
 
 #define GET_DEV_PORT(uport) \
 	container_of(uport, struct msm_geni_serial_port, uport)
 
+static struct msm_geni_serial_port msm_geni_console_port;
 static struct msm_geni_serial_port msm_geni_serial_ports[GENI_UART_NR_PORTS];
 
 static void msm_geni_serial_config_port(struct uart_port *uport, int cfg_flags)
@@ -177,22 +205,172 @@
 static DEVICE_ATTR(loopback, 0644, msm_geni_serial_loopback_show,
 					msm_geni_serial_loopback_store);
 
-static void msm_geni_serial_set_mctrl(struct uart_port *port,
+static void dump_ipc(void *ipc_ctx, char *prefix, char *string,
+						u64 addr, int size)
+
+{
+	char buf[DATA_BYTES_PER_LINE * 2];
+	int len = 0;
+
+	if (!ipc_ctx)
+		return;
+	len = min(size, DATA_BYTES_PER_LINE);
+	hex_dump_to_buffer(string, len, DATA_BYTES_PER_LINE, 1, buf,
+						sizeof(buf), false);
+	ipc_log_string(ipc_ctx, "%s[0x%.10x:%d] : %s", prefix,
+					(unsigned int)addr, size, buf);
+}
+
+static void check_tx_active(struct uart_port *uport)
+{
+	u32 geni_status = geni_read_reg_nolog(uport->membase,
+					SE_GENI_STATUS);
+
+	while ((geni_status & M_GENI_CMD_ACTIVE)) {
+		cpu_relax();
+		geni_status = geni_read_reg_nolog(uport->membase,
+					SE_GENI_STATUS);
+	}
+}
+
+static int vote_clock_on(struct uart_port *uport)
+{
+	int ret = 0;
+	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+
+	if (!pm_runtime_enabled(uport->dev)) {
+		dev_err(uport->dev, "RPM not available.Can't enable clocks\n");
+		ret = -EPERM;
+		return ret;
+	}
+	ret = msm_geni_serial_power_on(uport);
+	if (ret) {
+		dev_err(uport->dev, "Failed to vote clock on\n");
+		return ret;
+	}
+	__pm_relax(&port->geni_wake);
+	IPC_LOG_MSG(port->ipc_log_pwr, "%s\n", __func__);
+	return 0;
+}
+
+static int vote_clock_off(struct uart_port *uport)
+{
+	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+	int ret = 0;
+
+	if (!pm_runtime_enabled(uport->dev)) {
+		dev_err(uport->dev, "RPM not available.Can't enable clocks\n");
+		ret = -EPERM;
+		return ret;
+	}
+	/* Block till any on going Tx goes out.*/
+	check_tx_active(uport);
+	msm_geni_serial_power_off(uport);
+	IPC_LOG_MSG(port->ipc_log_pwr, "%s\n", __func__);
+	return 0;
+};
+
+static int msm_geni_serial_ioctl(struct uart_port *uport, unsigned int cmd,
+						unsigned long arg)
+{
+	int ret = -ENOIOCTLCMD;
+
+	switch (cmd) {
+	case TIOCPMGET: {
+		ret = vote_clock_on(uport);
+		break;
+	}
+	case TIOCPMPUT: {
+		ret = vote_clock_off(uport);
+		break;
+	}
+	case TIOCPMACT: {
+		ret = !pm_runtime_status_suspended(uport->dev);
+		break;
+	}
+	default:
+		break;
+	}
+	return ret;
+}
+
+static void msm_geni_serial_break_ctl(struct uart_port *uport, int ctl)
+{
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
+		dev_err(uport->dev, "%s Device suspended,vote clocks on.\n",
+							__func__);
+		return;
+	}
+
+	if (ctl) {
+		check_tx_active(uport);
+		geni_setup_m_cmd(uport->membase, UART_START_BREAK, 0);
+	} else {
+		geni_setup_m_cmd(uport->membase, UART_STOP_BREAK, 0);
+	}
+	/* Ensure break start/stop command is setup before returning.*/
+	mb();
+}
+
+static unsigned int msm_geni_serial_get_mctrl(struct uart_port *uport)
+{
+	u32 geni_ios = 0;
+	unsigned int mctrl = TIOCM_DSR | TIOCM_CAR;
+
+	if (pm_runtime_status_suspended(uport->dev))
+		return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS;
+
+	geni_ios = geni_read_reg_nolog(uport->membase, SE_GENI_IOS);
+	if (!(geni_ios & IO2_DATA_IN))
+		mctrl |= TIOCM_CTS;
+
+	return mctrl;
+}
+
+static void msm_geni_cons_set_mctrl(struct uart_port *uport,
 							unsigned int mctrl)
 {
 }
 
+static void msm_geni_serial_set_mctrl(struct uart_port *uport,
+							unsigned int mctrl)
+{
+	u32 uart_manual_rfr = 0;
+
+	if (pm_runtime_status_suspended(uport->dev)) {
+		dev_info(uport->dev, "%sDevice suspended,vote clocks on\n",
+						__func__);
+		return;
+	}
+	if (!(mctrl & TIOCM_RTS))
+		uart_manual_rfr |= (UART_MANUAL_RFR_EN | UART_RFR_NOT_READY);
+	geni_write_reg_nolog(uart_manual_rfr, uport->membase,
+							SE_UART_MANUAL_RFR);
+	/* Write to flow control must complete before return to client*/
+	mb();
+}
+
 static const char *msm_geni_serial_get_type(struct uart_port *uport)
 {
 	return "MSM";
 }
 
-static struct msm_geni_serial_port *get_port_from_line(int line)
+static struct msm_geni_serial_port *get_port_from_line(int line,
+						bool is_console)
 {
-	if ((line < 0) || (line >= GENI_UART_NR_PORTS))
-		return ERR_PTR(-ENXIO);
+	struct msm_geni_serial_port *port = NULL;
 
-	return &msm_geni_serial_ports[line];
+	if (is_console) {
+		if ((line < 0) || (line >= GENI_UART_CONS_PORTS))
+			port = ERR_PTR(-ENXIO);
+		port = &msm_geni_console_port;
+	} else {
+		if ((line < 0) || (line >= GENI_UART_NR_PORTS))
+			return ERR_PTR(-ENXIO);
+		port = &msm_geni_serial_ports[line];
+	}
+
+	return port;
 }
 
 static int msm_geni_serial_power_on(struct uart_port *uport)
@@ -201,16 +379,16 @@
 
 	ret = pm_runtime_get_sync(uport->dev);
 	if (ret < 0) {
-		dev_err(uport->dev, "%s: Failed (%d)", __func__, ret);
 		pm_runtime_put_noidle(uport->dev);
+		pm_runtime_set_suspended(uport->dev);
+		return ret;
 	}
-	return ret;
+	return 0;
 }
 
 static void msm_geni_serial_power_off(struct uart_port *uport)
 {
-	pm_runtime_mark_last_busy(uport->dev);
-	pm_runtime_put_autosuspend(uport->dev);
+	pm_runtime_put_sync(uport->dev);
 }
 
 static int msm_geni_serial_poll_bit(struct uart_port *uport,
@@ -219,9 +397,26 @@
 	int iter = 0;
 	unsigned int reg;
 	bool met = false;
+	struct msm_geni_serial_port *port = NULL;
 	bool cond = false;
+	unsigned int baud = 115200;
+	unsigned int fifo_bits = DEF_FIFO_DEPTH_WORDS * DEF_FIFO_WIDTH_BITS;
+	unsigned long total_iter = 0;
 
-	while (iter < 1000) {
+
+	if (uport->private_data) {
+		port = GET_DEV_PORT(uport);
+		baud = (port->cur_baud ? port->cur_baud : 115200);
+		fifo_bits = port->tx_fifo_depth * port->tx_fifo_width;
+	}
+	/*
+	 * Total polling iterations based on FIFO worth of bytes to be
+	 * sent at current baud .Add a little fluff to the wait.
+	 */
+	total_iter = ((fifo_bits * USEC_PER_SEC) / baud);
+	total_iter += 50;
+
+	while (iter < total_iter) {
 		reg = geni_read_reg_nolog(uport->membase, offset);
 		cond = reg & bit_field;
 		if (cond == set) {
@@ -293,23 +488,21 @@
 	unsigned int s_irq_status;
 
 	if (!(msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
-			M_SEC_IRQ_EN, true))) {
-		dev_err(uport->dev, "%s: Failed waiting for SE\n", __func__);
+			M_SEC_IRQ_EN, true)))
 		return -ENXIO;
-	}
 
 	m_irq_status = geni_read_reg_nolog(uport->membase,
 						SE_GENI_M_IRQ_STATUS);
 	s_irq_status = geni_read_reg_nolog(uport->membase,
 						SE_GENI_S_IRQ_STATUS);
-	geni_write_reg_nolog(m_irq_status, uport->membase, SE_GENI_M_IRQ_CLEAR);
-	geni_write_reg_nolog(s_irq_status, uport->membase, SE_GENI_S_IRQ_CLEAR);
+	geni_write_reg_nolog(m_irq_status, uport->membase,
+						SE_GENI_M_IRQ_CLEAR);
+	geni_write_reg_nolog(s_irq_status, uport->membase,
+						SE_GENI_S_IRQ_CLEAR);
 
 	if (!(msm_geni_serial_poll_bit(uport, SE_GENI_RX_FIFO_STATUS,
-			RX_FIFO_WC_MSK, true))) {
-		dev_err(uport->dev, "%s: Failed waiting for Rx\n", __func__);
+			RX_FIFO_WC_MSK, true)))
 		return -ENXIO;
-	}
 
 	/*
 	 * Read the Rx FIFO only after clearing the interrupt registers and
@@ -411,11 +604,9 @@
 
 	WARN_ON(co->index < 0 || co->index >= GENI_UART_NR_PORTS);
 
-	port = get_port_from_line(co->index);
-	if (IS_ERR_OR_NULL(port)) {
-		pr_err("%s:Invalid line %d\n", __func__, co->index);
+	port = get_port_from_line(co->index, true);
+	if (IS_ERR_OR_NULL(port))
 		return;
-	}
 
 	uport = &port->uport;
 	spin_lock(&uport->lock);
@@ -434,7 +625,6 @@
 	struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
 
 	tport = &uport->state->port;
-
 	for (i = 0; i < rx_fifo_wc; i++) {
 		int bytes = 4;
 
@@ -473,25 +663,35 @@
 static void msm_geni_serial_start_tx(struct uart_port *uport)
 {
 	unsigned int geni_m_irq_en;
-	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+	struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
 
 	if (!msm_geni_serial_tx_empty(uport))
 		return;
 
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev)) {
+		dev_err(uport->dev, "%s.Device is suspended.\n", __func__);
+		return;
+	}
+
 	geni_m_irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN);
 	geni_m_irq_en |= M_TX_FIFO_WATERMARK_EN;
 
-	geni_write_reg_nolog(port->tx_wm, uport->membase,
+	geni_write_reg_nolog(msm_port->tx_wm, uport->membase,
 						SE_GENI_TX_WATERMARK_REG);
 	geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN);
 	/* Geni command setup/irq enables should complete before returning.*/
 	mb();
+	IPC_LOG_MSG(msm_port->ipc_log_misc, "%s\n", __func__);
 }
 
 static void msm_geni_serial_stop_tx(struct uart_port *uport)
 {
 	unsigned int geni_m_irq_en;
 	unsigned int geni_status;
+	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+		return;
 
 	geni_m_irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN);
 	geni_m_irq_en &= ~(M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN);
@@ -514,6 +714,7 @@
 							SE_GENI_M_IRQ_CLEAR);
 	}
 	geni_write_reg_nolog(M_CMD_CANCEL_EN, uport, SE_GENI_M_IRQ_CLEAR);
+	IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__);
 }
 
 static void msm_geni_serial_start_rx(struct uart_port *uport)
@@ -522,8 +723,15 @@
 	unsigned int geni_m_irq_en;
 	unsigned long cfg0, cfg1;
 	unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT;
+	unsigned int geni_status;
+	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
 
-	msm_geni_serial_abort_rx(uport);
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+		return;
+
+	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
+	if (geni_status & S_GENI_CMD_ACTIVE)
+		msm_geni_serial_abort_rx(uport);
 	geni_s_irq_en = geni_read_reg_nolog(uport->membase,
 						SE_GENI_S_IRQ_EN);
 	geni_m_irq_en = geni_read_reg_nolog(uport->membase,
@@ -542,6 +750,7 @@
 	 * go through.
 	 */
 	mb();
+	IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__);
 }
 
 static void msm_geni_serial_stop_rx(struct uart_port *uport)
@@ -550,6 +759,9 @@
 	unsigned int geni_m_irq_en;
 	unsigned int geni_status;
 
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+		return;
+
 	geni_s_irq_en = geni_read_reg_nolog(uport->membase,
 						SE_GENI_S_IRQ_EN);
 	geni_m_irq_en = geni_read_reg_nolog(uport->membase,
@@ -595,6 +807,8 @@
 	}
 	uport->icount.rx += ret;
 	tty_flip_buffer_push(tport);
+	dump_ipc(msm_port->ipc_log_rx, "Rx", (char *)msm_port->rx_fifo, 0,
+								rx_bytes);
 	return ret;
 }
 
@@ -606,7 +820,7 @@
 	unsigned int rx_last_byte_valid = 0;
 	unsigned int rx_last = 0;
 	struct tty_port *tport;
-	struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
 
 	tport = &uport->state->port;
 	rx_fifo_status = geni_read_reg_nolog(uport->membase,
@@ -616,7 +830,7 @@
 						RX_LAST_BYTE_VALID_SHFT);
 	rx_last = rx_fifo_status & RX_LAST;
 	if (rx_fifo_wc)
-		msm_port->handle_rx(uport, rx_fifo_wc, rx_last_byte_valid,
+		port->handle_rx(uport, rx_fifo_wc, rx_last_byte_valid,
 								rx_last);
 	return ret;
 }
@@ -655,6 +869,8 @@
 	msm_geni_serial_setup_tx(uport, xmit_size);
 
 	bytes_remaining = xmit_size;
+	dump_ipc(msm_port->ipc_log_tx, "Tx", (char *)&xmit->buf[xmit->tail], 0,
+								xmit_size);
 	while (i < xmit_size) {
 		unsigned int tx_bytes;
 		unsigned int buf = 0;
@@ -688,12 +904,18 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&uport->lock, flags);
+	if (uart_console(uport) && uport->suspended)
+		goto exit_geni_serial_isr;
+	if (!uart_console(uport) && pm_runtime_status_suspended(uport->dev))
+		goto exit_geni_serial_isr;
 	m_irq_status = geni_read_reg_nolog(uport->membase,
-							SE_GENI_M_IRQ_STATUS);
+						SE_GENI_M_IRQ_STATUS);
 	s_irq_status = geni_read_reg_nolog(uport->membase,
-							SE_GENI_S_IRQ_STATUS);
-	geni_write_reg_nolog(m_irq_status, uport->membase, SE_GENI_M_IRQ_CLEAR);
-	geni_write_reg_nolog(s_irq_status, uport->membase, SE_GENI_S_IRQ_CLEAR);
+						SE_GENI_S_IRQ_STATUS);
+	geni_write_reg_nolog(m_irq_status, uport->membase,
+						SE_GENI_M_IRQ_CLEAR);
+	geni_write_reg_nolog(s_irq_status, uport->membase,
+						SE_GENI_S_IRQ_CLEAR);
 
 	if ((m_irq_status & M_ILLEGAL_CMD_EN)) {
 		WARN_ON(1);
@@ -713,6 +935,28 @@
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t msm_geni_wakeup_isr(int isr, void *dev)
+{
+	struct uart_port *uport = dev;
+	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+	struct tty_struct *tty;
+	unsigned long flags;
+
+	spin_lock_irqsave(&uport->lock, flags);
+	if (port->wakeup_byte) {
+		tty = uport->state->port.tty;
+		tty_insert_flip_char(tty->port, port->wakeup_byte, TTY_NORMAL);
+		IPC_LOG_MSG(port->ipc_log_rx, "%s: Inject 0x%x\n",
+					__func__, port->wakeup_byte);
+		tty_flip_buffer_push(tty->port);
+	}
+	__pm_wakeup_event(&port->geni_wake, WAKEBYTE_TIMEOUT_MSEC);
+	IPC_LOG_MSG(port->ipc_log_misc, "%s:Holding Wake Lock for %d ms\n",
+					__func__, WAKEBYTE_TIMEOUT_MSEC);
+	spin_unlock_irqrestore(&uport->lock, flags);
+	return IRQ_HANDLED;
+}
+
 static int get_tx_fifo_size(struct msm_geni_serial_port *port)
 {
 	struct uart_port *uport;
@@ -731,7 +975,7 @@
 	port->tx_fifo_width = get_tx_fifo_width(uport->membase);
 	if (!port->tx_fifo_width) {
 		dev_err(uport->dev, "%s:Invalid TX FIFO width read\n",
-								 __func__);
+								__func__);
 		return -ENXIO;
 	}
 
@@ -767,10 +1011,17 @@
 	msm_geni_serial_stop_rx(uport);
 	disable_irq(uport->irq);
 	free_irq(uport->irq, msm_port);
-	if (uart_console(uport))
+	if (uart_console(uport)) {
 		se_geni_resources_off(&msm_port->serial_rsc);
-	else
+	} else {
+		if (msm_port->wakeup_irq > 0) {
+			disable_irq(msm_port->wakeup_irq);
+			free_irq(msm_port->wakeup_irq, msm_port);
+		}
+		__pm_relax(&msm_port->geni_wake);
 		msm_geni_serial_power_off(uport);
+	}
+	IPC_LOG_MSG(msm_port->ipc_log_misc, "%s\n", __func__);
 }
 
 static int msm_geni_serial_port_setup(struct uart_port *uport)
@@ -780,10 +1031,10 @@
 	unsigned long cfg0, cfg1;
 
 
+	set_rfr_wm(msm_port);
 	if (!uart_console(uport)) {
 		/* For now only assume FIFO mode. */
 		msm_port->xfer_mode = FIFO_MODE;
-		set_rfr_wm(msm_port);
 		ret = geni_se_init(uport->membase, msm_port->xfer_mode,
 					msm_port->rx_wm, msm_port->rx_rfr);
 		if (ret) {
@@ -795,13 +1046,6 @@
 						SE_GENI_TX_PACKING_CFG0);
 		geni_write_reg_nolog(cfg1, uport->membase,
 						SE_GENI_TX_PACKING_CFG1);
-	} else {
-		set_rfr_wm(msm_port);
-		se_get_packing_config(8, 1, false, &cfg0, &cfg1);
-		geni_write_reg_nolog(cfg0, uport->membase,
-						SE_GENI_TX_PACKING_CFG0);
-		geni_write_reg_nolog(cfg1, uport->membase,
-						SE_GENI_TX_PACKING_CFG1);
 	}
 	msm_port->port_setup = true;
 	/*
@@ -809,6 +1053,47 @@
 	 * framework.
 	 */
 	mb();
+	if (!uart_console(uport)) {
+		char name[30];
+
+		memset(name, 0, sizeof(name));
+		if (!msm_port->ipc_log_rx) {
+			scnprintf(name, sizeof(name), "%s%s",
+					dev_name(uport->dev), "_rx");
+			msm_port->ipc_log_rx = ipc_log_context_create(
+					IPC_LOG_TX_RX_PAGES, name, 0);
+			if (!msm_port->ipc_log_rx)
+				dev_info(uport->dev, "Err in Rx IPC Log\n");
+		}
+		memset(name, 0, sizeof(name));
+		if (!msm_port->ipc_log_tx) {
+			scnprintf(name, sizeof(name), "%s%s",
+					dev_name(uport->dev), "_tx");
+			msm_port->ipc_log_tx = ipc_log_context_create(
+					IPC_LOG_TX_RX_PAGES, name, 0);
+			if (!msm_port->ipc_log_tx)
+				dev_info(uport->dev, "Err in Tx IPC Log\n");
+		}
+		memset(name, 0, sizeof(name));
+		if (!msm_port->ipc_log_pwr) {
+			scnprintf(name, sizeof(name), "%s%s",
+					dev_name(uport->dev), "_pwr");
+			msm_port->ipc_log_pwr = ipc_log_context_create(
+					IPC_LOG_PWR_PAGES, name, 0);
+			if (!msm_port->ipc_log_pwr)
+				dev_info(uport->dev, "Err in Pwr IPC Log\n");
+		}
+		memset(name, 0, sizeof(name));
+		if (!msm_port->ipc_log_misc) {
+			scnprintf(name, sizeof(name), "%s%s",
+					dev_name(uport->dev), "_misc");
+			msm_port->ipc_log_misc = ipc_log_context_create(
+					IPC_LOG_MISC_PAGES, name, 0);
+			if (!msm_port->ipc_log_misc)
+				dev_info(uport->dev, "Err in Misc IPC Log\n");
+		}
+
+	}
 exit_portsetup:
 	return ret;
 }
@@ -829,12 +1114,36 @@
 		goto exit_startup;
 	}
 
+	if (msm_port->wakeup_irq > 0) {
+		ret = request_threaded_irq(msm_port->wakeup_irq, NULL,
+				msm_geni_wakeup_isr,
+				IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+				"hs_uart_wakeup", uport);
+		if (unlikely(ret)) {
+			dev_err(uport->dev, "%s:Failed to get WakeIRQ ret%d\n",
+								__func__, ret);
+			goto exit_startup;
+		}
+		disable_irq(msm_port->wakeup_irq);
+	}
+
 	if (likely(!uart_console(uport))) {
 		ret = msm_geni_serial_power_on(&msm_port->uport);
 		if (ret)
 			goto exit_startup;
 	}
 
+	if (unlikely(get_se_proto(uport->membase) != UART)) {
+		dev_err(uport->dev, "%s: Invalid FW %d loaded.\n",
+				 __func__, get_se_proto(uport->membase));
+		if (unlikely(get_se_proto(uport->membase) != UART)) {
+			ret = -ENXIO;
+			disable_irq(uport->irq);
+			free_irq(uport->irq, msm_port);
+			goto exit_startup;
+		}
+	}
+
 	if (!msm_port->port_setup) {
 		if (msm_geni_serial_port_setup(uport))
 			goto exit_startup;
@@ -847,14 +1156,15 @@
 	 * before returning to the framework.
 	 */
 	mb();
+	IPC_LOG_MSG(msm_port->ipc_log_misc, "%s\n", __func__);
 exit_startup:
 	return ret;
 }
 
-static int get_dfs_index(unsigned long clk_freq, unsigned long *ser_clk)
+static int get_clk_cfg(unsigned long clk_freq, unsigned long *ser_clk)
 {
-	unsigned long root_freq[] = {19200000, 7372800, 64000000,
-			96000000, 100000000, 102400000, 128000000};
+	unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
+		32000000, 48000000, 64000000, 80000000, 96000000, 100000000};
 	int i;
 	int match = -1;
 
@@ -869,6 +1179,8 @@
 	}
 	if (match != -1)
 		*ser_clk = root_freq[match];
+	else
+		pr_err("clk_freq %ld\n", clk_freq);
 	return match;
 }
 
@@ -903,8 +1215,8 @@
 	int clk_div = 0;
 
 	*desired_clk_rate = baud * UART_OVERSAMPLING;
-	dfs_index = get_dfs_index(*desired_clk_rate, &ser_clk);
-	if (dfs_index < 1) {
+	dfs_index = get_clk_cfg(*desired_clk_rate, &ser_clk);
+	if (dfs_index < 0) {
 		pr_err("%s: Can't find matching DFS entry for baud %d\n",
 								__func__, baud);
 		clk_div = -EINVAL;
@@ -934,6 +1246,7 @@
 
 	/* baud rate */
 	baud = uart_get_baud_rate(uport, termios, old, 300, 4000000);
+	port->cur_baud = baud;
 	clk_div = get_clk_div_rate(baud, &clk_rate);
 	if (clk_div <= 0)
 		goto exit_set_termios;
@@ -1008,18 +1321,25 @@
 	geni_serial_write_term_regs(uport, port->loopback, tx_trans_cfg,
 		tx_parity_cfg, rx_trans_cfg, rx_parity_cfg, bits_per_char,
 		stop_bit_len, ser_clk_cfg);
+	IPC_LOG_MSG(port->ipc_log_misc, "%s: baud %d\n", __func__, baud);
+	IPC_LOG_MSG(port->ipc_log_misc, "Tx: trans_cfg%d parity %d\n",
+						tx_trans_cfg, tx_parity_cfg);
+	IPC_LOG_MSG(port->ipc_log_misc, "Rx: trans_cfg%d parity %d",
+						rx_trans_cfg, rx_parity_cfg);
+	IPC_LOG_MSG(port->ipc_log_misc, "BitsChar%d stop bit%d\n",
+				bits_per_char, stop_bit_len);
 exit_set_termios:
 	return;
 
 }
 
-static unsigned int msm_geni_serial_tx_empty(struct uart_port *port)
+static unsigned int msm_geni_serial_tx_empty(struct uart_port *uport)
 {
 	unsigned int tx_fifo_status;
 	unsigned int is_tx_empty = 1;
 
-	tx_fifo_status = geni_read_reg_nolog(port->membase,
-						SE_GENI_TX_FIFO_STATUS);
+	tx_fifo_status = geni_read_reg_nolog(uport->membase,
+					SE_GENI_TX_FIFO_STATUS);
 	if (tx_fifo_status)
 		is_tx_empty = 0;
 
@@ -1036,11 +1356,12 @@
 	int parity = 'n';
 	int flow = 'n';
 	int ret = 0;
+	unsigned long cfg0, cfg1;
 
 	if (unlikely(co->index >= GENI_UART_NR_PORTS  || co->index < 0))
 		return -ENXIO;
 
-	dev_port = get_port_from_line(co->index);
+	dev_port = get_port_from_line(co->index, true);
 	if (IS_ERR_OR_NULL(dev_port)) {
 		ret = PTR_ERR(dev_port);
 		pr_err("Invalid line %d(%d)\n", co->index, ret);
@@ -1068,6 +1389,9 @@
 	 * it else we could end up in data loss scenarios.
 	 */
 	msm_geni_serial_poll_cancel_tx(uport);
+	se_get_packing_config(8, 1, false, &cfg0, &cfg1);
+	geni_write_reg_nolog(cfg0, uport->membase, SE_GENI_TX_PACKING_CFG0);
+	geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_TX_PACKING_CFG1);
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 
@@ -1138,18 +1462,30 @@
 
 	s_clk_cfg |= SER_CLK_EN;
 	s_clk_cfg |= (clk_div << CLK_DIV_SHFT);
-	se_get_packing_config(8, 1, false, &cfg0, &cfg1);
-	geni_write_reg_nolog(cfg0, uport->membase, SE_GENI_TX_PACKING_CFG0);
-	geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_TX_PACKING_CFG1);
 
 	/*
 	 * Make an unconditional cancel on the main sequencer to reset
 	 * it else we could end up in data loss scenarios.
 	 */
 	msm_geni_serial_poll_cancel_tx(uport);
-	geni_serial_write_term_regs(uport, 0, tx_trans_cfg,
-		tx_parity_cfg, rx_trans_cfg, rx_parity_cfg, bits_per_char,
-		stop_bit, s_clk_cfg);
+	se_get_packing_config(8, 1, false, &cfg0, &cfg1);
+	geni_write_reg_nolog(cfg0, uport->membase, SE_GENI_TX_PACKING_CFG0);
+	geni_write_reg_nolog(cfg1, uport->membase, SE_GENI_TX_PACKING_CFG1);
+	geni_write_reg_nolog(tx_trans_cfg, uport->membase,
+							SE_UART_TX_TRANS_CFG);
+	geni_write_reg_nolog(tx_parity_cfg, uport->membase,
+							SE_UART_TX_PARITY_CFG);
+	geni_write_reg_nolog(rx_trans_cfg, uport->membase,
+							SE_UART_RX_TRANS_CFG);
+	geni_write_reg_nolog(rx_parity_cfg, uport->membase,
+							SE_UART_RX_PARITY_CFG);
+	geni_write_reg_nolog(bits_per_char, uport->membase,
+							SE_UART_TX_WORD_LEN);
+	geni_write_reg_nolog(bits_per_char, uport->membase,
+							SE_UART_RX_WORD_LEN);
+	geni_write_reg_nolog(stop_bit, uport->membase, SE_UART_TX_STOP_BIT_LEN);
+	geni_write_reg_nolog(s_clk_cfg, uport->membase, GENI_SER_M_CLK_CFG);
+	geni_write_reg_nolog(s_clk_cfg, uport->membase, GENI_SER_S_CLK_CFG);
 
 	dev->con->write = msm_geni_serial_early_console_write;
 	dev->con->setup = NULL;
@@ -1210,6 +1546,23 @@
 		dev_err(uport->dev, "Failed to create dbg dir\n");
 }
 
+static const struct uart_ops msm_geni_console_pops = {
+	.tx_empty = msm_geni_serial_tx_empty,
+	.stop_tx = msm_geni_serial_stop_tx,
+	.start_tx = msm_geni_serial_start_tx,
+	.stop_rx = msm_geni_serial_stop_rx,
+	.set_termios = msm_geni_serial_set_termios,
+	.startup = msm_geni_serial_startup,
+	.config_port = msm_geni_serial_config_port,
+	.shutdown = msm_geni_serial_shutdown,
+	.type = msm_geni_serial_get_type,
+	.set_mctrl = msm_geni_cons_set_mctrl,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char	= msm_geni_serial_get_char,
+	.poll_put_char	= msm_geni_serial_poll_put_char,
+#endif
+};
+
 static const struct uart_ops msm_geni_serial_pops = {
 	.tx_empty = msm_geni_serial_tx_empty,
 	.stop_tx = msm_geni_serial_stop_tx,
@@ -1221,10 +1574,10 @@
 	.shutdown = msm_geni_serial_shutdown,
 	.type = msm_geni_serial_get_type,
 	.set_mctrl = msm_geni_serial_set_mctrl,
-#ifdef CONFIG_CONSOLE_POLL
-	.poll_get_char	= msm_geni_serial_get_char,
-	.poll_put_char	= msm_geni_serial_poll_put_char,
-#endif
+	.get_mctrl = msm_geni_serial_get_mctrl,
+	.break_ctl = msm_geni_serial_break_ctl,
+	.flush_buffer = NULL,
+	.ioctl = msm_geni_serial_ioctl,
 };
 
 static const struct of_device_id msm_geni_device_tbl[] = {
@@ -1246,17 +1599,7 @@
 	struct resource *res;
 	struct uart_driver *drv;
 	const struct of_device_id *id;
-
-	if (pdev->dev.of_node)
-		line = of_alias_get_id(pdev->dev.of_node, "serial");
-	else
-		line = pdev->id;
-
-	if (line < 0)
-		line = atomic_inc_return(&uart_line_id) - 1;
-
-	if ((line < 0) || (line >= GENI_UART_NR_PORTS))
-		return -ENXIO;
+	bool is_console = false;
 
 	id = of_match_device(msm_geni_device_tbl, &pdev->dev);
 	if (id) {
@@ -1267,7 +1610,22 @@
 		return -ENODEV;
 	}
 
-	dev_port = get_port_from_line(line);
+	if (pdev->dev.of_node) {
+		if (drv->cons)
+			line = of_alias_get_id(pdev->dev.of_node, "serial");
+		else
+			line = of_alias_get_id(pdev->dev.of_node, "hsuart");
+	} else {
+		line = pdev->id;
+	}
+
+	if (line < 0)
+		line = atomic_inc_return(&uart_line_id) - 1;
+
+	if ((line < 0) || (line >= GENI_UART_NR_PORTS))
+		return -ENXIO;
+	is_console = (drv->cons ? true : false);
+	dev_port = get_port_from_line(line, is_console);
 	if (IS_ERR_OR_NULL(dev_port)) {
 		ret = PTR_ERR(dev_port);
 		dev_err(&pdev->dev, "Invalid line %d(%d)\n",
@@ -1300,9 +1658,13 @@
 		dev_port->serial_rsc.ab = UART_CORE2X_VOTE;
 		dev_port->serial_rsc.ib = DEFAULT_SE_CLK * DEFAULT_BUS_WIDTH;
 	} else {
-		dev_info(&pdev->dev, "No bus master specified");
+		dev_info(&pdev->dev, "No bus master specified\n");
 	}
 
+	if (of_property_read_u8(pdev->dev.of_node, "qcom,wakeup-byte",
+					&dev_port->wakeup_byte))
+		dev_info(&pdev->dev, "No Wakeup byte specified\n");
+
 	dev_port->serial_rsc.se_clk = devm_clk_get(&pdev->dev, "se-clk");
 	if (IS_ERR(dev_port->serial_rsc.se_clk)) {
 		ret = PTR_ERR(dev_port->serial_rsc.se_clk);
@@ -1363,6 +1725,7 @@
 		goto exit_geni_serial_probe;
 	}
 
+	wakeup_source_init(&dev_port->geni_wake, dev_name(&pdev->dev));
 	dev_port->tx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
 	dev_port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
 	dev_port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
@@ -1376,9 +1739,14 @@
 		goto exit_geni_serial_probe;
 	}
 
+	/* Optional to use the Rx pin as wakeup irq */
+	dev_port->wakeup_irq = platform_get_irq(pdev, 1);
+	if ((dev_port->wakeup_irq < 0 && !is_console))
+		dev_info(&pdev->dev, "No wakeup IRQ configured\n");
+
 	uport->private_data = (void *)drv;
 	platform_set_drvdata(pdev, dev_port);
-	if (drv->cons) {
+	if (is_console) {
 		dev_port->handle_rx = handle_rx_console;
 		dev_port->rx_fifo = devm_kzalloc(uport->dev, sizeof(u32),
 								GFP_KERNEL);
@@ -1387,13 +1755,11 @@
 		dev_port->rx_fifo = devm_kzalloc(uport->dev,
 				sizeof(dev_port->rx_fifo_depth * sizeof(u32)),
 								GFP_KERNEL);
-		pm_runtime_set_autosuspend_delay(&pdev->dev, MSEC_PER_SEC);
-		pm_runtime_use_autosuspend(&pdev->dev);
 		pm_runtime_enable(&pdev->dev);
 	}
 
 	dev_info(&pdev->dev, "Serial port%d added.FifoSize %d is_console%d\n",
-				line, uport->fifosize, (drv->cons ? 1 : 0));
+				line, uport->fifosize, is_console);
 	device_create_file(uport->dev, &dev_attr_loopback);
 	msm_geni_serial_debug_init(uport);
 	dev_port->port_setup = false;
@@ -1409,6 +1775,7 @@
 	struct uart_driver *drv =
 			(struct uart_driver *)port->uport.private_data;
 
+	wakeup_source_trash(&port->geni_wake);
 	uart_remove_one_port(drv, &port->uport);
 	msm_bus_scale_unregister(port->serial_rsc.bus_bw);
 	return 0;
@@ -1420,16 +1787,38 @@
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
+	int ret = 0;
 
-	return se_geni_resources_off(&port->serial_rsc);
+	ret = se_geni_resources_off(&port->serial_rsc);
+	if (ret) {
+		dev_err(dev, "%s: Error ret %d\n", __func__, ret);
+		goto exit_runtime_suspend;
+	}
+	if (port->wakeup_irq > 0)
+		enable_irq(port->wakeup_irq);
+	IPC_LOG_MSG(port->ipc_log_pwr, "%s: Current usage count %d\n", __func__,
+				atomic_read(&dev->power.usage_count));
+exit_runtime_suspend:
+	return ret;
 }
 
 static int msm_geni_serial_runtime_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
+	int ret = 0;
 
-	return se_geni_resources_on(&port->serial_rsc);
+	if (port->wakeup_irq > 0)
+		disable_irq(port->wakeup_irq);
+	ret = se_geni_resources_on(&port->serial_rsc);
+	if (ret) {
+		dev_err(dev, "%s: Error ret %d\n", __func__, ret);
+		goto exit_runtime_resume;
+	}
+	IPC_LOG_MSG(port->ipc_log_pwr, "%s: Current usage count %d\n", __func__,
+				atomic_read(&dev->power.usage_count));
+exit_runtime_resume:
+	return ret;
 }
 
 static int msm_geni_serial_sys_suspend_noirq(struct device *dev)
@@ -1527,6 +1916,13 @@
 		msm_geni_serial_ports[i].uport.line = i;
 	}
 
+	for (i = 0; i < GENI_UART_CONS_PORTS; i++) {
+		msm_geni_console_port.uport.iotype = UPIO_MEM;
+		msm_geni_console_port.uport.ops = &msm_geni_console_pops;
+		msm_geni_console_port.uport.flags = UPF_BOOT_AUTOCONF;
+		msm_geni_console_port.uport.line = i;
+	}
+
 	ret = console_register(&msm_geni_console_driver);
 	if (ret)
 		return ret;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 0dfe271..56df0f6 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -301,9 +301,6 @@
 	 */
 	if (dwc->ep0_bounced && dep->number <= 1) {
 		dwc->ep0_bounced = false;
-
-		usb_gadget_unmap_request_by_dev(dwc->sysdev,
-				&req->request, req->direction);
 		unmap_after_complete = true;
 	} else {
 		usb_gadget_unmap_request(&dwc->gadget,
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 12f2252..953275b 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -2080,11 +2080,6 @@
 	if (inode_dirty_flags)
 		__mark_inode_dirty(inode, inode_dirty_flags);
 
-	if (ia_valid & ATTR_MODE) {
-		err = posix_acl_chmod(inode, attr->ia_mode);
-		if (err)
-			goto out_put;
-	}
 
 	if (mask) {
 		req->r_inode = inode;
@@ -2098,13 +2093,11 @@
 	     ceph_cap_string(dirtied), mask);
 
 	ceph_mdsc_put_request(req);
-	if (mask & CEPH_SETATTR_SIZE)
+	ceph_free_cap_flush(prealloc_cf);
+
+	if (err >= 0 && (mask & CEPH_SETATTR_SIZE))
 		__ceph_do_pending_vmtruncate(inode);
-	ceph_free_cap_flush(prealloc_cf);
-	return err;
-out_put:
-	ceph_mdsc_put_request(req);
-	ceph_free_cap_flush(prealloc_cf);
+
 	return err;
 }
 
@@ -2123,7 +2116,12 @@
 	if (err != 0)
 		return err;
 
-	return __ceph_setattr(inode, attr);
+	err = __ceph_setattr(inode, attr);
+
+	if (err >= 0 && (attr->ia_valid & ATTR_MODE))
+		err = posix_acl_chmod(inode, attr->ia_mode);
+
+	return err;
 }
 
 /*
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index dba2ff8..4523346 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -358,6 +358,8 @@
 {
 	unsigned int len, v, hdr, dlen;
 	u32 max_blocksize = svc_max_payload(rqstp);
+	struct kvec *head = rqstp->rq_arg.head;
+	struct kvec *tail = rqstp->rq_arg.tail;
 
 	p = decode_fh(p, &args->fh);
 	if (!p)
@@ -367,6 +369,8 @@
 	args->count = ntohl(*p++);
 	args->stable = ntohl(*p++);
 	len = args->len = ntohl(*p++);
+	if ((void *)p > head->iov_base + head->iov_len)
+		return 0;
 	/*
 	 * The count must equal the amount of data passed.
 	 */
@@ -377,9 +381,8 @@
 	 * Check to make sure that we got the right number of
 	 * bytes.
 	 */
-	hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
-	dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
-		+ rqstp->rq_arg.tail[0].iov_len - hdr;
+	hdr = (void*)p - head->iov_base;
+	dlen = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len - hdr;
 	/*
 	 * Round the length of the data which was specified up to
 	 * the next multiple of XDR units and then compare that
@@ -396,7 +399,7 @@
 		len = args->len = max_blocksize;
 	}
 	rqstp->rq_vec[0].iov_base = (void*)p;
-	rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
+	rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
 	v = 0;
 	while (len > rqstp->rq_vec[v].iov_len) {
 		len -= rqstp->rq_vec[v].iov_len;
@@ -471,6 +474,8 @@
 	/* first copy and check from the first page */
 	old = (char*)p;
 	vec = &rqstp->rq_arg.head[0];
+	if ((void *)old > vec->iov_base + vec->iov_len)
+		return 0;
 	avail = vec->iov_len - (old - (char*)vec->iov_base);
 	while (len && avail && *old) {
 		*new++ = *old++;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index a2b65fc..1645b97 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -733,6 +733,37 @@
 	return nfserr;
 }
 
+/*
+ * A write procedure can have a large argument, and a read procedure can
+ * have a large reply, but no NFSv2 or NFSv3 procedure has argument and
+ * reply that can both be larger than a page.  The xdr code has taken
+ * advantage of this assumption to be a sloppy about bounds checking in
+ * some cases.  Pending a rewrite of the NFSv2/v3 xdr code to fix that
+ * problem, we enforce these assumptions here:
+ */
+static bool nfs_request_too_big(struct svc_rqst *rqstp,
+				struct svc_procedure *proc)
+{
+	/*
+	 * The ACL code has more careful bounds-checking and is not
+	 * susceptible to this problem:
+	 */
+	if (rqstp->rq_prog != NFS_PROGRAM)
+		return false;
+	/*
+	 * Ditto NFSv4 (which can in theory have argument and reply both
+	 * more than a page):
+	 */
+	if (rqstp->rq_vers >= 4)
+		return false;
+	/* The reply will be small, we're OK: */
+	if (proc->pc_xdrressize > 0 &&
+	    proc->pc_xdrressize < XDR_QUADLEN(PAGE_SIZE))
+		return false;
+
+	return rqstp->rq_arg.len > PAGE_SIZE;
+}
+
 int
 nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 {
@@ -745,6 +776,11 @@
 				rqstp->rq_vers, rqstp->rq_proc);
 	proc = rqstp->rq_procinfo;
 
+	if (nfs_request_too_big(rqstp, proc)) {
+		dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
+		*statp = rpc_garbage_args;
+		return 1;
+	}
 	/*
 	 * Give the xdr decoder a chance to change this if it wants
 	 * (necessary in the NFSv4.0 compound case)
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 41b468a..de07ff6 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -280,6 +280,7 @@
 					struct nfsd_writeargs *args)
 {
 	unsigned int len, hdr, dlen;
+	struct kvec *head = rqstp->rq_arg.head;
 	int v;
 
 	p = decode_fh(p, &args->fh);
@@ -300,9 +301,10 @@
 	 * Check to make sure that we got the right number of
 	 * bytes.
 	 */
-	hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
-	dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
-		- hdr;
+	hdr = (void*)p - head->iov_base;
+	if (hdr > head->iov_len)
+		return 0;
+	dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
 
 	/*
 	 * Round the length of the data which was specified up to
@@ -316,7 +318,7 @@
 		return 0;
 
 	rqstp->rq_vec[0].iov_base = (void*)p;
-	rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
+	rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
 	v = 0;
 	while (len > rqstp->rq_vec[v].iov_len) {
 		len -= rqstp->rq_vec[v].iov_len;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 1f6892c..e3d181e 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -436,6 +436,7 @@
 void iommu_fwspec_free(struct device *dev);
 int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
 int iommu_fwspec_get_id(struct device *dev, u32 *id);
+int iommu_is_available(struct device *dev);
 
 #else /* CONFIG_IOMMU_API */
 
@@ -711,6 +712,10 @@
 	return -ENODEV;
 }
 
+static inline int iommu_is_available(struct device *dev)
+{
+	return -ENODEV;
+}
 #endif /* CONFIG_IOMMU_API */
 
 #endif /* __LINUX_IOMMU_H */
diff --git a/include/linux/msm_pcie.h b/include/linux/msm_pcie.h
index 8316aaa..b9527d3 100644
--- a/include/linux/msm_pcie.h
+++ b/include/linux/msm_pcie.h
@@ -157,18 +157,6 @@
 int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base,
 			u32 offset, u32 mask, u32 value);
 
-/*
- * msm_pcie_configure_sid - calculates the SID for a PCIe endpoint.
- * @dev:	device structure
- * @sid:	the calculated SID
- * @domain:	the domain number of the Root Complex
- *
- * This function calculates the SID for a PCIe endpoint device.
- *
- * Return: 0 on success, negative value on error
- */
-int msm_pcie_configure_sid(struct device *dev, u32 *sid,
-			int *domain);
 #else /* !CONFIG_PCI_MSM */
 static inline int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr,
 			void *user, void *data, u32 options)
@@ -206,12 +194,6 @@
 {
 	return -ENODEV;
 }
-
-static inline int msm_pcie_configure_sid(struct device *dev, u32 *sid,
-			int *domain)
-{
-	return -ENODEV;
-}
 #endif /* CONFIG_PCI_MSM */
 
 #endif /* __MSM_PCIE_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index e25f183..bd22670 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -806,6 +806,7 @@
 void phy_mac_interrupt(struct phy_device *phydev, int new_link);
 void phy_start_machine(struct phy_device *phydev);
 void phy_stop_machine(struct phy_device *phydev);
+void phy_trigger_machine(struct phy_device *phydev, bool sync);
 int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
 int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
 int phy_ethtool_ksettings_get(struct phy_device *phydev,
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index 5a10db5..12b3d51e8 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -86,6 +86,7 @@
 #define SE_GENI_TX_WATERMARK_REG	(0x80C)
 #define SE_GENI_RX_WATERMARK_REG	(0x810)
 #define SE_GENI_RX_RFR_WATERMARK_REG	(0x814)
+#define SE_GENI_IOS			(0x908)
 #define SE_GENI_M_GP_LENGTH		(0x910)
 #define SE_GENI_S_GP_LENGTH		(0x914)
 #define SE_GSI_EVENT_EN			(0xE18)
@@ -228,6 +229,10 @@
 #define GENI_M_EVENT_EN		(BIT(2))
 #define GENI_S_EVENT_EN		(BIT(3))
 
+/* SE_GENI_IOS fields */
+#define IO2_DATA_IN		(BIT(1))
+#define RX_DATA_IN		(BIT(0))
+
 /* SE_IRQ_EN fields */
 #define DMA_RX_IRQ_EN		(BIT(0))
 #define DMA_TX_IRQ_EN		(BIT(1))
@@ -275,7 +280,7 @@
 static inline void geni_write_reg(unsigned int value, void __iomem *base,
 				int offset)
 {
-	return writel_relaxed(value, (base + offset));
+	writel_relaxed(value, (base + offset));
 }
 
 static inline int get_se_proto(void __iomem *base)
diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h
index 34434fd..75e6ccd 100644
--- a/include/soc/qcom/rpmh.h
+++ b/include/soc/qcom/rpmh.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,8 @@
 int rpmh_write_passthru(struct rpmh_client *rc, enum rpmh_state state,
 			struct tcs_cmd *cmd, int *n);
 
+int rpmh_mode_solver_set(struct rpmh_client *rc, bool enable);
+
 int rpmh_write_control(struct rpmh_client *rc, struct tcs_cmd *cmd, int n);
 
 int rpmh_invalidate(struct rpmh_client *rc);
@@ -70,6 +72,9 @@
 			enum rpmh_state state, struct tcs_cmd *cmd, int *n)
 { return -ENODEV; }
 
+static inline int rpmh_mode_solver_set(struct rpmh_client *rc, bool enable)
+{ return -ENODEV; }
+
 static inline int rpmh_write_control(struct rpmh_client *rc,
 			struct tcs_cmd *cmd, int n)
 { return -ENODEV; }
diff --git a/include/sound/voice_svc.h b/include/sound/voice_svc.h
deleted file mode 100644
index 035053f..0000000
--- a/include/sound/voice_svc.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef __VOICE_SVC_H__
-#define __VOICE_SVC_H__
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#define VOICE_SVC_DRIVER_NAME "voice_svc"
-
-#define VOICE_SVC_MVM_STR "MVM"
-#define VOICE_SVC_CVS_STR "CVS"
-#define MAX_APR_SERVICE_NAME_LEN  64
-
-#define MSG_REGISTER 0x1
-#define MSG_REQUEST  0x2
-#define MSG_RESPONSE 0x3
-
-struct voice_svc_write_msg {
-	__u32 msg_type;
-	__u8 payload[0];
-};
-
-struct voice_svc_register {
-	char svc_name[MAX_APR_SERVICE_NAME_LEN];
-	__u32 src_port;
-	__u8 reg_flag;
-};
-
-struct voice_svc_cmd_response {
-	__u32 src_port;
-	__u32 dest_port;
-	__u32 token;
-	__u32 opcode;
-	__u32 payload_size;
-	__u8 payload[0];
-};
-
-struct voice_svc_cmd_request {
-	char svc_name[MAX_APR_SERVICE_NAME_LEN];
-	__u32 src_port;
-	__u32 dest_port;
-	__u32 token;
-	__u32 opcode;
-	__u32 payload_size;
-	__u8 payload[0];
-};
-
-#endif
diff --git a/include/uapi/asm-generic/ioctls.h b/include/uapi/asm-generic/ioctls.h
index 143dacb..deb98c7 100644
--- a/include/uapi/asm-generic/ioctls.h
+++ b/include/uapi/asm-generic/ioctls.h
@@ -77,6 +77,9 @@
 #define TIOCGPKT	_IOR('T', 0x38, int) /* Get packet mode state */
 #define TIOCGPTLCK	_IOR('T', 0x39, int) /* Get Pty lock state */
 #define TIOCGEXCL	_IOR('T', 0x40, int) /* Get exclusive mode state */
+#define TIOCPMGET	0x5441	/* PM get */
+#define TIOCPMPUT	0x5442	/* PM put */
+#define TIOCPMACT	0x5443	/* PM is active */
 
 #define FIONCLEX	0x5450
 #define FIOCLEX		0x5451
diff --git a/include/uapi/linux/ipv6_route.h b/include/uapi/linux/ipv6_route.h
index f6598d1..316e838 100644
--- a/include/uapi/linux/ipv6_route.h
+++ b/include/uapi/linux/ipv6_route.h
@@ -34,7 +34,7 @@
 #define RTF_PREF(pref)	((pref) << 27)
 #define RTF_PREF_MASK	0x18000000
 
-#define RTF_PCPU	0x40000000
+#define RTF_PCPU	0x40000000	/* read-only: can not be set by user */
 #define RTF_LOCAL	0x80000000
 
 
diff --git a/include/uapi/media/Kbuild b/include/uapi/media/Kbuild
index 5f375c4..478f7fe 100644
--- a/include/uapi/media/Kbuild
+++ b/include/uapi/media/Kbuild
@@ -1,3 +1,4 @@
+header-y += cam_cpas.h
 header-y += cam_defs.h
 header-y += cam_isp.h
 header-y += cam_isp_vfe.h
diff --git a/include/uapi/media/cam_cpas.h b/include/uapi/media/cam_cpas.h
new file mode 100644
index 0000000..300bd87
--- /dev/null
+++ b/include/uapi/media/cam_cpas.h
@@ -0,0 +1,23 @@
+#ifndef __UAPI_CAM_CPAS_H__
+#define __UAPI_CAM_CPAS_H__
+
+#include "cam_defs.h"
+
+#define CAM_FAMILY_CAMERA_SS     1
+#define CAM_FAMILY_CPAS_SS       2
+
+/**
+ * struct cam_cpas_query_cap - CPAS query device capability payload
+ *
+ * @camera_family     : Camera family type
+ * @reserved          : Reserved field for alignment
+ * @camera_version    : Camera version
+ *
+ */
+struct cam_cpas_query_cap {
+	uint32_t                 camera_family;
+	uint32_t                 reserved;
+	struct cam_hw_version    camera_version;
+};
+
+#endif /* __UAPI_CAM_CPAS_H__ */
diff --git a/include/uapi/sound/Kbuild b/include/uapi/sound/Kbuild
index b0350f0..27e9ef8 100644
--- a/include/uapi/sound/Kbuild
+++ b/include/uapi/sound/Kbuild
@@ -18,7 +18,6 @@
 header-y += audio_slimslave.h
 header-y += voice_params.h
 header-y += audio_effects.h
-header-y += voice_svc.h
 header-y += devdep_params.h
 header-y += msmcal-hwdep.h
 header-y += wcd-dsp-glink.h
diff --git a/init/Kconfig b/init/Kconfig
index 007186d..2c382dc1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -795,19 +795,6 @@
 
 endchoice
 
-config RCU_EXPEDITE_BOOT
-	bool
-	default n
-	help
-	  This option enables expedited grace periods at boot time,
-	  as if rcu_expedite_gp() had been invoked early in boot.
-	  The corresponding rcu_unexpedite_gp() is invoked from
-	  rcu_end_inkernel_boot(), which is intended to be invoked
-	  at the end of the kernel-only boot sequence, just before
-	  init is exec'ed.
-
-	  Accept the default if unsure.
-
 endmenu # "RCU Subsystem"
 
 config BUILD_BIN2C
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 85d1c94..7c9f94c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1829,14 +1829,15 @@
 
 	for (i = 0; i < MAX_BPF_REG; i++)
 		if (regs[i].type == PTR_TO_PACKET && regs[i].id == dst_reg->id)
-			regs[i].range = dst_reg->off;
+			/* keep the maximum range already checked */
+			regs[i].range = max(regs[i].range, dst_reg->off);
 
 	for (i = 0; i < MAX_BPF_STACK; i += BPF_REG_SIZE) {
 		if (state->stack_slot_type[i] != STACK_SPILL)
 			continue;
 		reg = &state->spilled_regs[i / BPF_REG_SIZE];
 		if (reg->type == PTR_TO_PACKET && reg->id == dst_reg->id)
-			reg->range = dst_reg->off;
+			reg->range = max(reg->range, dst_reg->off);
 	}
 }
 
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
index 4f6db7e..9e03db9 100644
--- a/kernel/rcu/update.c
+++ b/kernel/rcu/update.c
@@ -132,8 +132,7 @@
 }
 EXPORT_SYMBOL_GPL(rcu_gp_is_normal);
 
-static atomic_t rcu_expedited_nesting =
-	ATOMIC_INIT(IS_ENABLED(CONFIG_RCU_EXPEDITE_BOOT) ? 1 : 0);
+static atomic_t rcu_expedited_nesting = ATOMIC_INIT(1);
 
 /*
  * Should normal grace-period primitives be expedited?  Intended for
@@ -182,8 +181,7 @@
  */
 void rcu_end_inkernel_boot(void)
 {
-	if (IS_ENABLED(CONFIG_RCU_EXPEDITE_BOOT))
-		rcu_unexpedite_gp();
+	rcu_unexpedite_gp();
 	if (rcu_normal_after_boot)
 		WRITE_ONCE(rcu_normal, 1);
 }
diff --git a/net/9p/client.c b/net/9p/client.c
index 3fc94a4..cf129fe 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -2101,6 +2101,10 @@
 		trace_9p_protocol_dump(clnt, req->rc);
 		goto free_and_error;
 	}
+	if (rsize < count) {
+		pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize);
+		count = rsize;
+	}
 
 	p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
 
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 9901e5b..f45f619 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -859,7 +859,8 @@
 	if (skb)
 		skb = skb_clone(skb, GFP_ATOMIC);
 	write_unlock(&neigh->lock);
-	neigh->ops->solicit(neigh, skb);
+	if (neigh->ops->solicit)
+		neigh->ops->solicit(neigh, skb);
 	atomic_inc(&neigh->probes);
 	kfree_skb(skb);
 }
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 53599bd..457f882 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -105,15 +105,21 @@
 	while ((skb = skb_dequeue(&npinfo->txq))) {
 		struct net_device *dev = skb->dev;
 		struct netdev_queue *txq;
+		unsigned int q_index;
 
 		if (!netif_device_present(dev) || !netif_running(dev)) {
 			kfree_skb(skb);
 			continue;
 		}
 
-		txq = skb_get_tx_queue(dev, skb);
-
 		local_irq_save(flags);
+		/* check if skb->queue_mapping is still valid */
+		q_index = skb_get_queue_mapping(skb);
+		if (unlikely(q_index >= dev->real_num_tx_queues)) {
+			q_index = q_index % dev->real_num_tx_queues;
+			skb_set_queue_mapping(skb, q_index);
+		}
+		txq = netdev_get_tx_queue(dev, q_index);
 		HARD_TX_LOCK(dev, txq, smp_processor_id());
 		if (netif_xmit_frozen_or_stopped(txq) ||
 		    netpoll_start_xmit(skb, dev, txq) != NETDEV_TX_OK) {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 8de6707..ba1146c 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3082,22 +3082,32 @@
 	if (sg && csum && (mss != GSO_BY_FRAGS))  {
 		if (!(features & NETIF_F_GSO_PARTIAL)) {
 			struct sk_buff *iter;
+			unsigned int frag_len;
 
 			if (!list_skb ||
 			    !net_gso_ok(features, skb_shinfo(head_skb)->gso_type))
 				goto normal;
 
-			/* Split the buffer at the frag_list pointer.
-			 * This is based on the assumption that all
-			 * buffers in the chain excluding the last
-			 * containing the same amount of data.
+			/* If we get here then all the required
+			 * GSO features except frag_list are supported.
+			 * Try to split the SKB to multiple GSO SKBs
+			 * with no frag_list.
+			 * Currently we can do that only when the buffers don't
+			 * have a linear part and all the buffers except
+			 * the last are of the same length.
 			 */
+			frag_len = list_skb->len;
 			skb_walk_frags(head_skb, iter) {
+				if (frag_len != iter->len && iter->next)
+					goto normal;
 				if (skb_headlen(iter))
 					goto normal;
 
 				len -= iter->len;
 			}
+
+			if (len != frag_len)
+				goto normal;
 		}
 
 		/* GSO partial only requires that we trim off any excess that
@@ -3785,6 +3795,7 @@
 	serr->ee.ee_errno = ENOMSG;
 	serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
 	serr->ee.ee_info = tstype;
+	serr->header.h4.iif = skb->dev ? skb->dev->ifindex : 0;
 	if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) {
 		serr->ee.ee_data = skb_shinfo(skb)->tskey;
 		if (sk->sk_protocol == IPPROTO_TCP &&
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 9826695..4d37bdc 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -474,16 +474,15 @@
 		return false;
 
 	/* Support IP_PKTINFO on tstamp packets if requested, to correlate
-	 * timestamp with egress dev. Not possible for packets without dev
+	 * timestamp with egress dev. Not possible for packets without iif
 	 * or without payload (SOF_TIMESTAMPING_OPT_TSONLY).
 	 */
-	if ((!(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_CMSG)) ||
-	    (!skb->dev))
+	info = PKTINFO_SKB_CB(skb);
+	if (!(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_CMSG) ||
+	    !info->ipi_ifindex)
 		return false;
 
-	info = PKTINFO_SKB_CB(skb);
 	info->ipi_spec_dst.s_addr = ip_hdr(skb)->saddr;
-	info->ipi_ifindex = skb->dev->ifindex;
 	return true;
 }
 
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 06879e6..93bfadf 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -156,17 +156,18 @@
 void ping_unhash(struct sock *sk)
 {
 	struct inet_sock *isk = inet_sk(sk);
+
 	pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num);
+	write_lock_bh(&ping_table.lock);
 	if (sk_hashed(sk)) {
-		write_lock_bh(&ping_table.lock);
 		hlist_nulls_del(&sk->sk_nulls_node);
 		sk_nulls_node_init(&sk->sk_nulls_node);
 		sock_put(sk);
 		isk->inet_num = 0;
 		isk->inet_sport = 0;
 		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
-		write_unlock_bh(&ping_table.lock);
 	}
+	write_unlock_bh(&ping_table.lock);
 }
 EXPORT_SYMBOL_GPL(ping_unhash);
 
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index e6acef5..70c40ba2 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2581,7 +2581,7 @@
 	skb_reset_network_header(skb);
 
 	/* Bugfix: need to give ip_route_input enough of an IP header to not gag. */
-	ip_hdr(skb)->protocol = IPPROTO_ICMP;
+	ip_hdr(skb)->protocol = IPPROTO_UDP;
 	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
 
 	src = tb[RTA_SRC] ? nla_get_in_addr(tb[RTA_SRC]) : 0;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 6a90a0e..eb142ca 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2297,6 +2297,7 @@
 	tcp_init_send_head(sk);
 	memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
 	__sk_dst_reset(sk);
+	tcp_saved_syn_free(tp);
 
 	WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
 
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index f9038d6b..baea5df 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -167,12 +167,8 @@
 	}
 out:
 	rcu_read_unlock();
+	memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
 
-	/* Clear out private data before diag gets it and
-	 * the ca has not been initialized.
-	 */
-	if (ca->get_info)
-		memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
 	if (ca->flags & TCP_CONG_NEEDS_ECN)
 		INET_ECN_xmit(sk);
 	else
@@ -199,11 +195,10 @@
 	tcp_cleanup_congestion_control(sk);
 	icsk->icsk_ca_ops = ca;
 	icsk->icsk_ca_setsockopt = 1;
+	memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
 
-	if (sk->sk_state != TCP_CLOSE) {
-		memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
+	if (sk->sk_state != TCP_CLOSE)
 		tcp_init_congestion_control(sk);
-	}
 }
 
 /* Manage refcounts on socket close. */
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 7588fa9..553138d 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3293,14 +3293,24 @@
 static int fixup_permanent_addr(struct inet6_dev *idev,
 				struct inet6_ifaddr *ifp)
 {
-	if (!ifp->rt) {
-		struct rt6_info *rt;
+	/* rt6i_ref == 0 means the host route was removed from the
+	 * FIB, for example, if 'lo' device is taken down. In that
+	 * case regenerate the host route.
+	 */
+	if (!ifp->rt || !atomic_read(&ifp->rt->rt6i_ref)) {
+		struct rt6_info *rt, *prev;
 
 		rt = addrconf_dst_alloc(idev, &ifp->addr, false);
 		if (unlikely(IS_ERR(rt)))
 			return PTR_ERR(rt);
 
+		/* ifp->rt can be accessed outside of rtnl */
+		spin_lock(&ifp->lock);
+		prev = ifp->rt;
 		ifp->rt = rt;
+		spin_unlock(&ifp->lock);
+
+		ip6_rt_put(prev);
 	}
 
 	if (!(ifp->flags & IFA_F_NOPREFIXROUTE)) {
@@ -3642,14 +3652,19 @@
 	INIT_LIST_HEAD(&del_list);
 	list_for_each_entry_safe(ifa, tmp, &idev->addr_list, if_list) {
 		struct rt6_info *rt = NULL;
+		bool keep;
 
 		addrconf_del_dad_work(ifa);
 
+		keep = keep_addr && (ifa->flags & IFA_F_PERMANENT) &&
+			!addr_is_local(&ifa->addr);
+		if (!keep)
+			list_move(&ifa->if_list, &del_list);
+
 		write_unlock_bh(&idev->lock);
 		spin_lock_bh(&ifa->lock);
 
-		if (keep_addr && (ifa->flags & IFA_F_PERMANENT) &&
-		    !addr_is_local(&ifa->addr)) {
+		if (keep) {
 			/* set state to skip the notifier below */
 			state = INET6_IFADDR_STATE_DEAD;
 			ifa->state = 0;
@@ -3661,8 +3676,6 @@
 		} else {
 			state = ifa->state;
 			ifa->state = INET6_IFADDR_STATE_DEAD;
-
-			list_move(&ifa->if_list, &del_list);
 		}
 
 		spin_unlock_bh(&ifa->lock);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 1529833..a381772 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -401,9 +401,6 @@
  * At one point, excluding local errors was a quick test to identify icmp/icmp6
  * errors. This is no longer true, but the test remained, so the v6 stack,
  * unlike v4, also honors cmsg requests on all wifi and timestamp errors.
- *
- * Timestamp code paths do not initialize the fields expected by cmsg:
- * the PKTINFO fields in skb->cb[]. Fill those in here.
  */
 static bool ip6_datagram_support_cmsg(struct sk_buff *skb,
 				      struct sock_exterr_skb *serr)
@@ -415,14 +412,9 @@
 	if (serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL)
 		return false;
 
-	if (!skb->dev)
+	if (!IP6CB(skb)->iif)
 		return false;
 
-	if (skb->protocol == htons(ETH_P_IPV6))
-		IP6CB(skb)->iif = skb->dev->ifindex;
-	else
-		PKTINFO_SKB_CB(skb)->ipi_ifindex = skb->dev->ifindex;
-
 	return true;
 }
 
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 885b411..97e89a2 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1037,7 +1037,7 @@
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct net *net = t->net;
 	struct net_device_stats *stats = &t->dev->stats;
-	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+	struct ipv6hdr *ipv6h;
 	struct ipv6_tel_txoption opt;
 	struct dst_entry *dst = NULL, *ndst = NULL;
 	struct net_device *tdev;
@@ -1057,26 +1057,28 @@
 
 	/* NBMA tunnel */
 	if (ipv6_addr_any(&t->parms.raddr)) {
-		struct in6_addr *addr6;
-		struct neighbour *neigh;
-		int addr_type;
+		if (skb->protocol == htons(ETH_P_IPV6)) {
+			struct in6_addr *addr6;
+			struct neighbour *neigh;
+			int addr_type;
 
-		if (!skb_dst(skb))
-			goto tx_err_link_failure;
+			if (!skb_dst(skb))
+				goto tx_err_link_failure;
 
-		neigh = dst_neigh_lookup(skb_dst(skb),
-					 &ipv6_hdr(skb)->daddr);
-		if (!neigh)
-			goto tx_err_link_failure;
+			neigh = dst_neigh_lookup(skb_dst(skb),
+						 &ipv6_hdr(skb)->daddr);
+			if (!neigh)
+				goto tx_err_link_failure;
 
-		addr6 = (struct in6_addr *)&neigh->primary_key;
-		addr_type = ipv6_addr_type(addr6);
+			addr6 = (struct in6_addr *)&neigh->primary_key;
+			addr_type = ipv6_addr_type(addr6);
 
-		if (addr_type == IPV6_ADDR_ANY)
-			addr6 = &ipv6_hdr(skb)->daddr;
+			if (addr_type == IPV6_ADDR_ANY)
+				addr6 = &ipv6_hdr(skb)->daddr;
 
-		memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
-		neigh_release(neigh);
+			memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
+			neigh_release(neigh);
+		}
 	} else if (!(t->parms.flags &
 		     (IP6_TNL_F_USE_ORIG_TCLASS | IP6_TNL_F_USE_ORIG_FWMARK))) {
 		/* enable the cache only only if the routing decision does
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 7f4265b..117405d 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -774,7 +774,8 @@
  *	Delete a VIF entry
  */
 
-static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head)
+static int mif6_delete(struct mr6_table *mrt, int vifi, int notify,
+		       struct list_head *head)
 {
 	struct mif_device *v;
 	struct net_device *dev;
@@ -820,7 +821,7 @@
 					     dev->ifindex, &in6_dev->cnf);
 	}
 
-	if (v->flags & MIFF_REGISTER)
+	if ((v->flags & MIFF_REGISTER) && !notify)
 		unregister_netdevice_queue(dev, head);
 
 	dev_put(dev);
@@ -1331,7 +1332,6 @@
 	struct mr6_table *mrt;
 	struct mif_device *v;
 	int ct;
-	LIST_HEAD(list);
 
 	if (event != NETDEV_UNREGISTER)
 		return NOTIFY_DONE;
@@ -1340,10 +1340,9 @@
 		v = &mrt->vif6_table[0];
 		for (ct = 0; ct < mrt->maxvif; ct++, v++) {
 			if (v->dev == dev)
-				mif6_delete(mrt, ct, &list);
+				mif6_delete(mrt, ct, 1, NULL);
 		}
 	}
-	unregister_netdevice_many(&list);
 
 	return NOTIFY_DONE;
 }
@@ -1552,7 +1551,7 @@
 	for (i = 0; i < mrt->maxvif; i++) {
 		if (!all && (mrt->vif6_table[i].flags & VIFF_STATIC))
 			continue;
-		mif6_delete(mrt, i, &list);
+		mif6_delete(mrt, i, 0, &list);
 	}
 	unregister_netdevice_many(&list);
 
@@ -1706,7 +1705,7 @@
 		if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
 			return -EFAULT;
 		rtnl_lock();
-		ret = mif6_delete(mrt, mifi, NULL);
+		ret = mif6_delete(mrt, mifi, 0, NULL);
 		rtnl_unlock();
 		return ret;
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 5665375..1a34da0 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -1172,8 +1172,7 @@
 		spin_lock_bh(&sk->sk_receive_queue.lock);
 		skb = skb_peek(&sk->sk_receive_queue);
 		if (skb)
-			amount = skb_tail_pointer(skb) -
-				skb_transport_header(skb);
+			amount = skb->len;
 		spin_unlock_bh(&sk->sk_receive_queue.lock);
 		return put_user(amount, (int __user *)arg);
 	}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 73527d8..7d17670 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1825,6 +1825,10 @@
 	int addr_type;
 	int err = -EINVAL;
 
+	/* RTF_PCPU is an internal flag; can not be set by userspace */
+	if (cfg->fc_flags & RTF_PCPU)
+		goto out;
+
 	if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128)
 		goto out;
 #ifndef CONFIG_IPV6_SUBTREES
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index a646f34..fecad10 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -1685,7 +1685,7 @@
 		struct kcm_attach info;
 
 		if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
-			err = -EFAULT;
+			return -EFAULT;
 
 		err = kcm_attach_ioctl(sock, &info);
 
@@ -1695,7 +1695,7 @@
 		struct kcm_unattach info;
 
 		if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
-			err = -EFAULT;
+			return -EFAULT;
 
 		err = kcm_unattach_ioctl(sock, &info);
 
@@ -1706,7 +1706,7 @@
 		struct socket *newsock = NULL;
 
 		if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
-			err = -EFAULT;
+			return -EFAULT;
 
 		err = kcm_clone(sock, &info, &newsock);
 
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index a2ed3bd..e702cb95 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -278,7 +278,8 @@
 }
 EXPORT_SYMBOL_GPL(l2tp_session_find);
 
-struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth)
+struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
+					  bool do_ref)
 {
 	int hash;
 	struct l2tp_session *session;
@@ -288,6 +289,9 @@
 	for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
 		hlist_for_each_entry(session, &tunnel->session_hlist[hash], hlist) {
 			if (++count > nth) {
+				l2tp_session_inc_refcount(session);
+				if (do_ref && session->ref)
+					session->ref(session);
 				read_unlock_bh(&tunnel->hlist_lock);
 				return session;
 			}
@@ -298,7 +302,7 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(l2tp_session_find_nth);
+EXPORT_SYMBOL_GPL(l2tp_session_get_nth);
 
 /* Lookup a session by interface name.
  * This is very inefficient but is only used by management interfaces.
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 181e755c..e7233ba 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -243,7 +243,8 @@
 struct l2tp_session *l2tp_session_find(struct net *net,
 				       struct l2tp_tunnel *tunnel,
 				       u32 session_id);
-struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth);
+struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
+					  bool do_ref);
 struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname);
 struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id);
 struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth);
diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c
index 2d6760a..d100aed 100644
--- a/net/l2tp/l2tp_debugfs.c
+++ b/net/l2tp/l2tp_debugfs.c
@@ -53,7 +53,7 @@
 
 static void l2tp_dfs_next_session(struct l2tp_dfs_seq_data *pd)
 {
-	pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx);
+	pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true);
 	pd->session_idx++;
 
 	if (pd->session == NULL) {
@@ -238,10 +238,14 @@
 	}
 
 	/* Show the tunnel or session context */
-	if (pd->session == NULL)
+	if (!pd->session) {
 		l2tp_dfs_seq_tunnel_show(m, pd->tunnel);
-	else
+	} else {
 		l2tp_dfs_seq_session_show(m, pd->session);
+		if (pd->session->deref)
+			pd->session->deref(pd->session);
+		l2tp_session_dec_refcount(pd->session);
+	}
 
 out:
 	return 0;
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index ff750bb..2066953 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -178,9 +178,10 @@
 
 	tunnel_id = ntohl(*(__be32 *) &skb->data[4]);
 	tunnel = l2tp_tunnel_find(net, tunnel_id);
-	if (tunnel != NULL)
+	if (tunnel) {
 		sk = tunnel->sock;
-	else {
+		sock_hold(sk);
+	} else {
 		struct iphdr *iph = (struct iphdr *) skb_network_header(skb);
 
 		read_lock_bh(&l2tp_ip_lock);
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 7095786..26cf4dc 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -191,9 +191,10 @@
 
 	tunnel_id = ntohl(*(__be32 *) &skb->data[4]);
 	tunnel = l2tp_tunnel_find(net, tunnel_id);
-	if (tunnel != NULL)
+	if (tunnel) {
 		sk = tunnel->sock;
-	else {
+		sock_hold(sk);
+	} else {
 		struct ipv6hdr *iph = ipv6_hdr(skb);
 
 		read_lock_bh(&l2tp_ip6_lock);
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index bf31177..9f66272 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -844,7 +844,7 @@
 				goto out;
 		}
 
-		session = l2tp_session_find_nth(tunnel, si);
+		session = l2tp_session_get_nth(tunnel, si, false);
 		if (session == NULL) {
 			ti++;
 			tunnel = NULL;
@@ -854,8 +854,11 @@
 
 		if (l2tp_nl_session_send(skb, NETLINK_CB(cb->skb).portid,
 					 cb->nlh->nlmsg_seq, NLM_F_MULTI,
-					 session, L2TP_CMD_SESSION_GET) < 0)
+					 session, L2TP_CMD_SESSION_GET) < 0) {
+			l2tp_session_dec_refcount(session);
 			break;
+		}
+		l2tp_session_dec_refcount(session);
 
 		si++;
 	}
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 41d47bf..1387f54 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -450,6 +450,10 @@
 static void pppol2tp_session_destruct(struct sock *sk)
 {
 	struct l2tp_session *session = sk->sk_user_data;
+
+	skb_queue_purge(&sk->sk_receive_queue);
+	skb_queue_purge(&sk->sk_write_queue);
+
 	if (session) {
 		sk->sk_user_data = NULL;
 		BUG_ON(session->magic != L2TP_SESSION_MAGIC);
@@ -488,9 +492,6 @@
 		l2tp_session_queue_purge(session);
 		sock_put(sk);
 	}
-	skb_queue_purge(&sk->sk_receive_queue);
-	skb_queue_purge(&sk->sk_write_queue);
-
 	release_sock(sk);
 
 	/* This will delete the session context via
@@ -1554,7 +1555,7 @@
 
 static void pppol2tp_next_session(struct net *net, struct pppol2tp_seq_data *pd)
 {
-	pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx);
+	pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true);
 	pd->session_idx++;
 
 	if (pd->session == NULL) {
@@ -1681,10 +1682,14 @@
 
 	/* Show the tunnel or session context.
 	 */
-	if (pd->session == NULL)
+	if (!pd->session) {
 		pppol2tp_seq_tunnel_show(m, pd->tunnel);
-	else
+	} else {
 		pppol2tp_seq_session_show(m, pd->session);
+		if (pd->session->deref)
+			pd->session->deref(pd->session);
+		l2tp_session_dec_refcount(pd->session);
+	}
 
 out:
 	return 0;
@@ -1843,4 +1848,4 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(PPPOL2TP_DRV_VERSION);
 MODULE_ALIAS_NET_PF_PROTO(PF_PPPOX, PX_PROTO_OL2TP);
-MODULE_ALIAS_L2TP_PWTYPE(11);
+MODULE_ALIAS_L2TP_PWTYPE(7);
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index 0f5628a..3c7ae04 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -969,9 +969,8 @@
 		for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
 			IF_DEBUG("qtaguid: iface_stat: create(%s): "
 				 "ifa=%p ifa_label=%s\n",
-				 ifname, ifa,
-				 ifa->ifa_label ? ifa->ifa_label : "(null)");
-			if (ifa->ifa_label && !strcmp(ifname, ifa->ifa_label))
+				 ifname, ifa, ifa->ifa_label);
+			if (!strcmp(ifname, ifa->ifa_label))
 				break;
 		}
 	}
@@ -1209,10 +1208,6 @@
 		pr_err_ratelimited("qtaguid[%d]: %s(): no par->in/out?!!\n",
 				   par->hooknum, __func__);
 		BUG();
-	} else if (unlikely(!el_dev->name)) {
-		pr_err_ratelimited("qtaguid[%d]: %s(): no dev->name?!!\n",
-				   par->hooknum, __func__);
-		BUG();
 	} else {
 		proto = ipx_proto(skb, par);
 		MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n",
@@ -1637,8 +1632,6 @@
 
 	if (unlikely(!el_dev)) {
 		pr_info("qtaguid[%d]: no par->in/out?!!\n", par->hooknum);
-	} else if (unlikely(!el_dev->name)) {
-		pr_info("qtaguid[%d]: no dev->name?!!\n", par->hooknum);
 	} else {
 		int proto = ipx_proto(skb, par);
 		MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n",
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8ab0974..cb76ff3 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -3702,6 +3702,8 @@
 			return -EBUSY;
 		if (copy_from_user(&val, optval, sizeof(val)))
 			return -EFAULT;
+		if (val > INT_MAX)
+			return -EINVAL;
 		po->tp_reserve = val;
 		return 0;
 	}
@@ -4247,6 +4249,8 @@
 		rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
 		if (unlikely(rb->frames_per_block == 0))
 			goto out;
+		if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+			goto out;
 		if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
 					req->tp_frame_nr))
 			goto out;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 6734420..14346dc 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6861,6 +6861,9 @@
 	if (sock->state != SS_UNCONNECTED)
 		goto out;
 
+	if (!sctp_sstate(sk, LISTENING) && !sctp_sstate(sk, CLOSED))
+		goto out;
+
 	/* If backlog is zero, disable listening. */
 	if (!backlog) {
 		if (sctp_sstate(sk, CLOSED))
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c
index 3b693e9..12ba833 100644
--- a/sound/core/seq/seq_lock.c
+++ b/sound/core/seq/seq_lock.c
@@ -28,19 +28,16 @@
 /* wait until all locks are released */
 void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line)
 {
-	int max_count = 5 * HZ;
+	int warn_count = 5 * HZ;
 
 	if (atomic_read(lockp) < 0) {
 		pr_warn("ALSA: seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line);
 		return;
 	}
 	while (atomic_read(lockp) > 0) {
-		if (max_count == 0) {
-			pr_warn("ALSA: seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line);
-			break;
-		}
+		if (warn_count-- == 0)
+			pr_warn("ALSA: seq_lock: waiting [%d left] in %s:%d\n", atomic_read(lockp), file, line);
 		schedule_timeout_uninterruptible(1);
-		max_count--;
 	}
 }
 
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h
index f676931..c3768cd 100644
--- a/sound/firewire/lib.h
+++ b/sound/firewire/lib.h
@@ -45,7 +45,7 @@
 
 	struct snd_rawmidi_substream *substream;
 	snd_fw_async_midi_port_fill fill;
-	unsigned int consume_bytes;
+	int consume_bytes;
 };
 
 int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port,
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c
index e629b88..474b06d 100644
--- a/sound/firewire/oxfw/oxfw.c
+++ b/sound/firewire/oxfw/oxfw.c
@@ -226,11 +226,11 @@
 	if (err < 0)
 		goto error;
 
-	err = detect_quirks(oxfw);
+	err = snd_oxfw_stream_discover(oxfw);
 	if (err < 0)
 		goto error;
 
-	err = snd_oxfw_stream_discover(oxfw);
+	err = detect_quirks(oxfw);
 	if (err < 0)
 		goto error;
 
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 4c8ff29..d5873ee 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -621,7 +621,7 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 		.platform_name = "sst-mfld-platform",
-		.ignore_suspend = 1,
+		.nonatomic = true,
 		.dynamic = 1,
 		.dpcm_playback = 1,
 		.dpcm_capture = 1,
@@ -634,7 +634,6 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 		.platform_name = "sst-mfld-platform",
-		.ignore_suspend = 1,
 		.nonatomic = true,
 		.dynamic = 1,
 		.dpcm_playback = 1,
@@ -661,6 +660,7 @@
 						| SND_SOC_DAIFMT_CBS_CFS,
 		.be_hw_params_fixup = byt_rt5640_codec_fixup,
 		.ignore_suspend = 1,
+		.nonatomic = true,
 		.dpcm_playback = 1,
 		.dpcm_capture = 1,
 		.init = byt_rt5640_init,
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 35f591e..eabff3a 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -235,7 +235,6 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 		.platform_name = "sst-mfld-platform",
-		.ignore_suspend = 1,
 		.nonatomic = true,
 		.dynamic = 1,
 		.dpcm_playback = 1,
@@ -249,7 +248,6 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 		.platform_name = "sst-mfld-platform",
-		.ignore_suspend = 1,
 		.nonatomic = true,
 		.dynamic = 1,
 		.dpcm_playback = 1,