Merge "msm: bam_dmux: remove A2_DEFAULT_DESCRIPTORS"
diff --git a/arch/arm/boot/dts/msm8974-fluid.dts b/arch/arm/boot/dts/msm8974-fluid.dts
new file mode 100644
index 0000000..b1d467e
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-fluid.dts
@@ -0,0 +1,366 @@
+/* Copyright (c) 2012, 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974.dtsi"
+/include/ "dsi-panel-toshiba-720p-video.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974 FLUID";
+	compatible = "qcom,msm8974-fluid", "qcom,msm8974";
+	qcom,msm-id = <126 3 0>;
+
+	serial@f991e000 {
+		status = "ok";
+	};
+
+	qcom,mdss_dsi@fd922800 {
+		qcom,mdss_dsi_toshiba_720p_video {
+			status = "ok";
+		};
+	};
+
+	i2c@f9924000 {
+		atmel_mxt_ts@4a {
+			compatible = "atmel,mxt-ts";
+			reg = <0x4a>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <61 0x2>;
+			vdd_ana-supply = <&pm8941_l18>;
+			vcc_i2c-supply = <&pm8941_lvs1>;
+			atmel,reset-gpio = <&msmgpio 60 0x00>;
+			atmel,irq-gpio = <&msmgpio 61 0x00>;
+			atmel,panel-coords = <0  0 760 1424>;
+			atmel,display-coords = <0 0 720 1280>;
+			atmel,i2c-pull-up = <1>;
+			atmel,cfg_1 {
+				atmel,family-id = <0x82>;
+				atmel,variant-id = <0x19>;
+				atmel,version = <0x10>;
+				atmel,build = <0xaa>;
+				atmel,config = [
+					/* Object 6, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 38, Instance = 0 */
+					15 00 02 10 08 0C 00 00
+					/* Object 7, Instance = 0 */
+					FF FF 32 03
+					/* Object 8, Instance = 0 */
+					0F 00 0A 0A 00 00 0A 00 00 00
+					/* Object 9, Instance = 0 */
+					83 00 00 18 0E 00 70 32 02 01
+					00 03 01 01 05 0A 0A 0A 90 05
+					F8 02 00 00 0F 0F 00 00 48 2D
+					07 0C 00 00 00 00
+					/* Object 15, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00
+					/* Object 18, Instance = 0 */
+					00 00
+					/* Object 19, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 23, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 25, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					00 00 00 00 00
+					/* Object 40, Instance = 0 */
+					00 00 00 00 00
+					/* Object 42, Instance = 0 */
+					00 00 00 00 00 00 00 00 00 00
+					/* Object 46, Instance = 0 */
+					00 00 10 10 00 00 03 00 00 01
+					/* Object 47, Instance = 0 */
+					08 0A 28 0A 02 0A 00 8C 00 20
+					00 00 00
+					/* Object 55, Instance = 0 */
+					00 00 00 00 00 00
+					/* Object 56, Instance = 0 */
+					03 00 01 18 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 05 05
+					05 05 05 05 05 05 05 05 00 00
+					00 00 00 00 00 00 00 00 00 00
+					00 00
+					/* Object 57, Instance = 0 */
+					00 00 00
+					/* Object 61, Instance = 0 */
+					00 00 00 00 00
+					/* Object 61, Instance = 1 */
+					00 00 00 00 00
+					/* Object 62, Instance = 0 */
+					7F 03 00 16 00 00 00 00 00 00
+					04 08 10 18 05 00 0A 05 05 50
+					14 19 34 1A 64 00 00 04 40 00
+					00 00 00 00 30 32 02 00 01 00
+					05 00 00 00 00 00 00 00 00 00
+					00 00 0C 00
+					];
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&pm8941_gpios 3 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&pm8941_gpios 4 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&pm8941_gpios 5 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+	};
+
+	spi@f9923000 {
+		ethernet-switch@2 {
+			compatible = "micrel,ks8851";
+			reg = <2>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <94 0>;
+			spi-max-frequency = <4800000>;
+			rst-gpio = <&pm8941_mpps 6 0>;
+			vdd-io-supply = <&spi_eth_vreg>;
+			vdd-phy-supply = <&spi_eth_vreg>;
+		};
+	};
+};
+
+&sdcc1 {
+	qcom,sdcc-bus-width = <4>;
+};
+
+&sdcc2 {
+	#address-cells = <0>;
+	interrupt-parent = <&sdcc2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 220 0
+			2 &msmgpio 62 0x3>;
+	interrupt-names = "core_irq", "bam_irq", "status_irq";
+	cd-gpios = <&msmgpio 62 0x1>;
+};
+
+&pm8941_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c300 { /* GPIO 4 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c400 { /* GPIO 5 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+
+	gpio@c800 { /* GPIO 9 */
+	};
+
+	gpio@c900 { /* GPIO 10 */
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+		qcom,mode = <1>;
+		qcom,output-type = <0>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-select = <2>;
+		qcom,master-en = <1>;
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+	};
+
+	gpio@d000 { /* GPIO 17 */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,master-en = <1>;
+	};
+
+	gpio@d300 { /* GPIO 20 */
+	};
+
+	gpio@d400 { /* GPIO 21 */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+	};
+
+	gpio@d600 { /* GPIO 23 */
+	};
+
+	gpio@d700 { /* GPIO 24 */
+	};
+
+	gpio@d800 { /* GPIO 25 */
+	};
+
+	gpio@d900 { /* GPIO 26 */
+	};
+
+	gpio@da00 { /* GPIO 27 */
+	};
+
+	gpio@db00 { /* GPIO 28 */
+	};
+
+	gpio@dc00 { /* GPIO 29 */
+		qcom,pull = <0>; /* set to default pull */
+		qcom,master-en = <1>;
+		qcom,vin-sel = <2>; /* select 1.8 V source */
+	};
+
+	gpio@dd00 { /* GPIO 30 */
+	};
+
+	gpio@de00 { /* GPIO 31 */
+	};
+
+	gpio@df00 { /* GPIO 32 */
+	};
+
+	gpio@e000 { /* GPIO 33 */
+	};
+
+	gpio@e100 { /* GPIO 34 */
+	};
+
+	gpio@e200 { /* GPIO 35 */
+	};
+
+	gpio@e300 { /* GPIO 36 */
+	};
+};
+
+&pm8941_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+		/* SPI_ETH config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* SPI_ETH_RST config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
+
+&pm8841_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index ee5836c..ca98706 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -18,6 +18,8 @@
 		reg-names = "mdp_phys", "vbif_phys";
 		interrupts = <0 72 0>;
 		vdd-supply = <&gdsc_mdss>;
+		qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
+		qcom,memory-reservation-size = <0x800000>; /* size 8MB */
 	};
 
 	mdss_dsi: qcom,mdss_dsi@fd922800 {
diff --git a/arch/arm/boot/dts/msm8974-mtp.dts b/arch/arm/boot/dts/msm8974-mtp.dts
index e183d04..00aec9f 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-mtp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -18,7 +18,7 @@
 / {
 	model = "Qualcomm MSM 8974 MTP";
 	compatible = "qcom,msm8974-mtp", "qcom,msm8974";
-	qcom,msm-id = <126 8 0>, <126 3 0>;
+	qcom,msm-id = <126 8 0>;
 
 	serial@f991e000 {
 		status = "ok";
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 157f159..2020422 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1909,7 +1909,7 @@
 
 config MSM_PIL_QDSP6V3
 	tristate "QDSP6v3 (Hexagon) Boot Support"
-	depends on MSM_PIL
+	depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
 	help
 	  Support for booting and shutting down QDSP6v3 processors (hexagon).
 	  The QDSP6 is a low power DSP used in audio software applications.
@@ -1945,7 +1945,7 @@
 
 config MSM_PIL_RIVA
 	tristate "RIVA (WCNSS) Boot Support"
-	depends on MSM_PIL
+	depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
 	help
 	  Support for booting and shutting down the RIVA processor (WCNSS).
 	  Riva is the wireless subsystem processor used in bluetooth, wireless
@@ -1984,8 +1984,8 @@
 	  Venus is the Video subsystem processor used for video codecs.
 
 config MSM_PIL_GSS
-	tristate "GSS (Coretx A5) Boot Support"
-	depends on MSM_PIL
+	tristate "GSS (Cortex A5) Boot Support"
+	depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
 	help
 	  Support for booting and shutting down Cortex A5 processors which run
 	  GPS subsystem firmware.
@@ -2018,22 +2018,6 @@
 	 lpass hardware watchdog interrupt lines and plugs into the subsystem
 	 restart and PIL drivers. For MSM9615, it only supports a full chip reset.
 
-config MSM_WCNSS_SSR_8960
-	tristate "MSM 8960 WCNSS restart module"
-	depends on (ARCH_MSM8960)
-	help
-	 This option enables the WCNSS restart module for MSM8960, which
-	 monitors WCNSS hardware watchdog interrupt lines and plugs WCNSS
-	 into the subsystem restart framework.
-
-config MSM_GSS_SSR_8064
-	bool "MSM 8064 GSS restart driver"
-	depends on (ARCH_APQ8064)
-	help
-	 This option enables the gps subsystem restart driver for APQ8064, which monitors
-	 gss hardware watchdog interrupt lines and plugs into the subsystem
-	 restart and PIL drivers.
-
 config MSM_MODEM_SSR_8974
 	bool "MSM 8974 Modem restart driver"
 	depends on (ARCH_MSM8974)
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 1b42d2d..7dece76 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -195,15 +195,12 @@
 	obj-y += subsystem_notif.o
 	obj-y += subsystem_restart.o
 	obj-y += ramdump.o
-	obj-$(CONFIG_ARCH_MSM8X60) += lpass-8660.o
 endif
 obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o
 obj-$(CONFIG_MSM_MODEM_8960) += modem-8960.o
 obj-$(CONFIG_MSM_MODEM_SSR_8974) += modem-ssr-8974.o
 obj-$(CONFIG_MSM_LPASS_8960) += lpass-8960.o
 obj-$(CONFIG_MSM_ADSP_SSR_8974) += adsp-8974.o
-obj-$(CONFIG_MSM_WCNSS_SSR_8960) += wcnss-ssr-8960.o
-obj-$(CONFIG_MSM_GSS_SSR_8064) += gss-8064.o
 
 ifdef CONFIG_CPU_IDLE
 	obj-$(CONFIG_ARCH_APQ8064) += cpuidle.o
@@ -351,7 +348,7 @@
 obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
 
 obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o
-obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_dcvs_idle.o
+obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_dcvs_idle.o msm_mpdecision.o
 obj-$(CONFIG_MSM_RUN_QUEUE_STATS) += msm_rq_stats.o
 obj-$(CONFIG_MSM_SHOW_RESUME_IRQ) += msm_show_resume_irq.o
 obj-$(CONFIG_BT_MSM_PINTEST)  += btpintest.o
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 32ef39f..7ba22f4 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -222,6 +222,7 @@
 static void rx_timer_work_func(struct work_struct *work);
 
 static DECLARE_WORK(rx_timer_work, rx_timer_work_func);
+static struct delayed_work queue_rx_work;
 
 static struct workqueue_struct *bam_mux_rx_workqueue;
 static struct workqueue_struct *bam_mux_tx_workqueue;
@@ -429,21 +430,27 @@
 	rx_len_cached = bam_rx_pool_len;
 	mutex_unlock(&bam_rx_pool_mutexlock);
 
-	while (rx_len_cached < NUM_BUFFERS) {
+	while (bam_connection_is_active && rx_len_cached < NUM_BUFFERS) {
 		if (in_global_reset)
 			goto fail;
 
-		info = kmalloc(sizeof(struct rx_pkt_info), GFP_KERNEL);
+		info = kmalloc(sizeof(struct rx_pkt_info),
+						GFP_NOWAIT | __GFP_NOWARN);
 		if (!info) {
-			pr_err("%s: unable to alloc rx_pkt_info\n", __func__);
+			DMUX_LOG_KERR(
+			"%s: unable to alloc rx_pkt_info, will retry later\n",
+								__func__);
 			goto fail;
 		}
 
 		INIT_WORK(&info->work, handle_bam_mux_cmd);
 
-		info->skb = __dev_alloc_skb(BUFFER_SIZE, GFP_KERNEL);
+		info->skb = __dev_alloc_skb(BUFFER_SIZE,
+						GFP_NOWAIT | __GFP_NOWARN);
 		if (info->skb == NULL) {
-			DMUX_LOG_KERR("%s: unable to alloc skb\n", __func__);
+			DMUX_LOG_KERR(
+				"%s: unable to alloc skb, will retry later\n",
+								__func__);
 			goto fail_info;
 		}
 		ptr = skb_put(info->skb, BUFFER_SIZE);
@@ -487,11 +494,16 @@
 
 fail:
 	if (rx_len_cached == 0) {
-		DMUX_LOG_KERR("%s: RX queue failure\n", __func__);
-		in_global_reset = 1;
+		DMUX_LOG_KERR("%s: rescheduling\n", __func__);
+		schedule_delayed_work(&queue_rx_work, msecs_to_jiffies(100));
 	}
 }
 
+static void queue_rx_work_func(struct work_struct *work)
+{
+	queue_rx();
+}
+
 static void bam_mux_process_data(struct sk_buff *rx_skb)
 {
 	unsigned long flags;
@@ -2421,6 +2433,7 @@
 	init_completion(&bam_connection_completion);
 	init_completion(&dfab_unvote_completion);
 	INIT_DELAYED_WORK(&ul_timeout_work, ul_timeout);
+	INIT_DELAYED_WORK(&queue_rx_work, queue_rx_work_func);
 	wake_lock_init(&bam_wakelock, WAKE_LOCK_SUSPEND, "bam_dmux_wakelock");
 
 	rc = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_A2_POWER_CONTROL,
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 6eadc59..f6423c8 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -115,7 +115,6 @@
 /* Initial PM8921 GPIO configurations */
 static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
 	PM8921_GPIO_OUTPUT(14, 1, HIGH),	/* HDMI Mux Selector */
-	PM8921_GPIO_OUTPUT(23, 0, HIGH),	/* touchscreen power FET */
 	PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
 	PM8921_GPIO_OUTPUT_FUNC(26, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
 	PM8921_GPIO_OUTPUT_VIN(30, 1, PM_GPIO_VIN_VPH), /* SMB349 susp line */
@@ -146,10 +145,13 @@
 	PM8921_GPIO_OUTPUT(37, 0, LOW),	/* MUX1_SEL */
 };
 
+static struct pm8xxx_gpio_init touchscreen_gpios[] __initdata = {
+	PM8921_GPIO_OUTPUT(23, 0, HIGH),	/* touchscreen power FET */
+};
+
 /* Initial PM8917 GPIO configurations */
 static struct pm8xxx_gpio_init pm8917_gpios[] __initdata = {
 	PM8921_GPIO_OUTPUT(14, 1, HIGH),	/* HDMI Mux Selector */
-	PM8921_GPIO_OUTPUT(23, 0, HIGH),	/* touchscreen power FET */
 	PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
 	PM8921_GPIO_OUTPUT(26, 1, HIGH), /* Backlight: on */
 	PM8921_GPIO_OUTPUT_BUFCONF(36, 1, LOW, OPEN_DRAIN),
@@ -210,6 +212,8 @@
 		apq8064_configure_gpios(pm8917_gpios, ARRAY_SIZE(pm8917_gpios));
 
 	if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid()) {
+		apq8064_configure_gpios(touchscreen_gpios,
+					ARRAY_SIZE(touchscreen_gpios));
 		if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
 			apq8064_configure_gpios(pm8921_cdp_kp_gpios,
 					ARRAY_SIZE(pm8921_cdp_kp_gpios));
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 6cdafbc..ef3c81d 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -771,4 +771,10 @@
 				= ARRAY_SIZE(vreg_consumers_8917_S1);
 		}
 	}
+
+	/*
+	 * Switch to 8960_PM8917 rpm-regulator version so that TCXO workaround
+	 * is applied to PM8917 regulators L25, L26, L27, and L28.
+	 */
+	apq8064_rpm_regulator_pdata.version = RPM_VREG_VERSION_8960_PM8917;
 }
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 2fd1a68..cc9dcbb 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -927,7 +927,8 @@
 static void __init apq8064_ehci_host_init(void)
 {
 	if (machine_is_apq8064_liquid() || machine_is_mpq8064_cdp() ||
-		machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()) {
+		machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv() ||
+					machine_is_apq8064_cdp()) {
 		if (machine_is_apq8064_liquid())
 			msm_ehci_host_pdata3.dock_connect_irq =
 					PM8921_MPP_IRQ(PM8921_IRQ_BASE, 9);
@@ -2467,7 +2468,6 @@
 	&apq8064_device_ext_3p3v_vreg,
 	&apq8064_device_ssbi_pmic1,
 	&apq8064_device_ssbi_pmic2,
-	&apq8064_device_ext_ts_sw_vreg,
 };
 
 static struct platform_device *pm8917_common_devices[] __initdata = {
@@ -2475,7 +2475,6 @@
 	&apq8064_device_ext_3p3v_vreg,
 	&apq8064_device_ssbi_pmic1,
 	&apq8064_device_ssbi_pmic2,
-	&apq8064_device_ext_ts_sw_vreg,
 };
 
 static struct platform_device *common_devices[] __initdata = {
@@ -2570,6 +2569,7 @@
 	&msm_gss,
 	&apq8064_rtb_device,
 	&apq8064_cpu_idle_device,
+	&apq8064_msm_gov_device,
 	&apq8064_device_cache_erp,
 	&msm8960_device_ebi1_ch0_erp,
 	&msm8960_device_ebi1_ch1_erp,
@@ -2593,6 +2593,7 @@
 #ifdef CONFIG_BATTERY_BCL
 	&battery_bcl_device,
 #endif
+	&apq8064_msm_mpd_device,
 };
 
 static struct platform_device *cdp_devices[] __initdata = {
@@ -3372,6 +3373,8 @@
 	else
 		platform_add_devices(pm8917_common_devices,
 					ARRAY_SIZE(pm8917_common_devices));
+	if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+		platform_device_register(&apq8064_device_ext_ts_sw_vreg);
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	if (!(machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
 			machine_is_mpq8064_dtv()))
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 797f5f1..37e93b6 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -31,8 +31,39 @@
 #include <mach/gpio.h>
 #include <mach/clk-provider.h>
 #include <mach/qpnp-int.h>
+#include <mach/msm_memtypes.h>
 #include "clock.h"
 
+#define MSM_KERNEL_EBI_SIZE	0x51000
+
+static struct memtype_reserve msm9625_reserve_table[] __initdata = {
+	[MEMTYPE_SMI] = {
+	},
+	[MEMTYPE_EBI0] = {
+		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
+	},
+	[MEMTYPE_EBI1] = {
+		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
+	},
+};
+
+static int msm9625_paddr_to_memtype(unsigned int paddr)
+{
+	return MEMTYPE_EBI1;
+}
+
+static void __init msm9625_calculate_reserve_sizes(void)
+{
+	msm9625_reserve_table[MEMTYPE_EBI1].size += MSM_KERNEL_EBI_SIZE;
+}
+
+static struct reserve_info msm9625_reserve_info __initdata = {
+	.memtype_reserve_table = msm9625_reserve_table,
+	.calculate_reserve_sizes = msm9625_calculate_reserve_sizes,
+	.paddr_to_memtype = msm9625_paddr_to_memtype,
+};
+
+
 #define L2CC_AUX_CTRL	((0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) | \
 			(0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | \
 			(0x1 << L2X0_AUX_CTRL_EVNT_MON_BUS_EN_SHIFT))
@@ -97,6 +128,13 @@
 	.init = msm_dt_timer_init
 };
 
+static void __init msm9625_reserve(void)
+{
+	reserve_info = &msm9625_reserve_info;
+	msm_reserve();
+}
+
+
 void __init msm9625_init(void)
 {
 	if (socinfo_init() < 0)
@@ -115,4 +153,5 @@
 	.handle_irq = gic_handle_irq,
 	.timer = &msm_dt_timer,
 	.dt_compat = msm9625_dt_match,
+	.reserve = msm9625_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index b4f6968..1d6eb01 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -941,6 +941,8 @@
 
 static void __init fsm9xxx_init(void)
 {
+	msm_clock_init(&fsm9xxx_clock_init_data);
+
 	regulator_has_full_constraints();
 
 #if defined(CONFIG_I2C_SSBI) || defined(CONFIG_MSM_SSBI)
@@ -977,7 +979,6 @@
 {
 	msm_shared_ram_phys = 0x00100000;
 	msm_map_fsm9xxx_io();
-	msm_clock_init(&fsm9xxx_clock_init_data);
 	if (socinfo_init() < 0)
 		pr_err("%s: socinfo_init() failed!\n",
 		       __func__);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index c0461e1..6d964e2 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -1962,6 +1962,11 @@
 		.end    = 0x10008000 + SZ_256 - 1,
 		.flags  = IORESOURCE_MEM,
 	},
+	{
+		.start	= GSS_A5_WDOG_EXPIRED,
+		.end	= GSS_A5_WDOG_EXPIRED,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 struct platform_device msm_gss = {
@@ -2691,6 +2696,23 @@
 	},
 };
 
+static struct msm_mpd_algo_param apq8064_mpd_algo_param = {
+	.em_win_size_min_us	= 10000,
+	.em_win_size_max_us	= 100000,
+	.em_max_util_pct	= 90,
+	.online_util_pct_min	= 60,
+	.slack_time_min_us	= 50000,
+	.slack_time_max_us	= 100000,
+};
+
+struct platform_device apq8064_msm_mpd_device = {
+	.name	= "msm_mpdecision",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &apq8064_mpd_algo_param,
+	},
+};
+
 #ifdef CONFIG_MSM_VCAP
 #define VCAP_HW_BASE         0x05900000
 
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 5cbfb5b..2a641ba 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1444,6 +1444,11 @@
 		.end    = 0x03204000 + SZ_256 - 1,
 		.flags  = IORESOURCE_MEM,
 	},
+	{
+		.start  = RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
+		.end    = RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
+		.flags  = IORESOURCE_IRQ,
+	},
 };
 
 struct platform_device msm_8960_riva = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 0a9bbf6..46853ac 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1316,8 +1316,8 @@
 };
 
 static struct msm_rpmstats_platform_data msm_rpm_stat_pdata = {
-	.phys_addr_base = 0x0010D204,
-	.phys_size = SZ_8K,
+	.phys_addr_base = 0x0010DD04,
+	.phys_size = SZ_256,
 };
 
 struct platform_device msm9615_rpm_stat_device = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index b88fb50..37cdc98 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -192,7 +192,9 @@
 	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, (void *)MSM_QGIC_CPU_BASE);
 }
 
-#define MSM_LPASS_QDSP6SS_PHYS 0x28800000
+#define MSM_LPASS_QDSP6SS_PHYS		0x28800000
+#define MSM_LPASS_QDSP6SS_WDOG_PHYS	0x28882000
+#define MSM_LPASS_QDSP6SS_IM_PHYS	0x288A0000
 
 static struct resource msm_8660_q6_resources[] = {
 	{
@@ -200,6 +202,21 @@
 		.end    = MSM_LPASS_QDSP6SS_PHYS + SZ_256 - 1,
 		.flags  = IORESOURCE_MEM,
 	},
+	{
+		.start  = MSM_LPASS_QDSP6SS_IM_PHYS,
+		.end    = MSM_LPASS_QDSP6SS_IM_PHYS + SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = MSM_LPASS_QDSP6SS_WDOG_PHYS,
+		.end    = MSM_LPASS_QDSP6SS_WDOG_PHYS + SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start	= LPASS_Q6SS_WDOG_EXPIRED,
+		.end	= LPASS_Q6SS_WDOG_EXPIRED,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 struct platform_device msm_pil_q6v3 = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 0506217..7e750f5 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-msm/devices.h
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -447,6 +447,8 @@
 extern struct platform_device msm8960ab_device_acpuclk;
 extern struct platform_device msm9615_device_acpuclk;
 
+extern struct platform_device apq8064_msm_mpd_device;
+
 extern struct platform_device msm_gpio_device;
 
 extern struct platform_device apq_cpudai_mi2s;
diff --git a/arch/arm/mach-msm/gss-8064.c b/arch/arm/mach-msm/gss-8064.c
deleted file mode 100644
index ba6af61..0000000
--- a/arch/arm/mach-msm/gss-8064.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/* Copyright (c) 2012, Code Aurora Forum. 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/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-
-#include <mach/irqs.h>
-#include <mach/msm_smsm.h>
-#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-#include <mach/socinfo.h>
-
-#include "smd_private.h"
-#include "modem_notifier.h"
-#include "ramdump.h"
-
-static struct gss_8064_data {
-	struct miscdevice gss_dev;
-	void *pil_handle;
-	void *gss_ramdump_dev;
-	void *smem_ramdump_dev;
-} gss_data;
-
-static int crash_shutdown;
-
-static struct subsys_device *gss_8064_dev;
-
-#define MAX_SSR_REASON_LEN 81U
-
-static void log_gss_sfr(void)
-{
-	u32 size;
-	char *smem_reason, reason[MAX_SSR_REASON_LEN];
-
-	smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
-	if (!smem_reason || !size) {
-		pr_err("GSS subsystem failure reason: (unknown, smem_get_entry failed).\n");
-		return;
-	}
-	if (!smem_reason[0]) {
-		pr_err("GSS subsystem failure reason: (unknown, init string found).\n");
-		return;
-	}
-
-	size = min(size, MAX_SSR_REASON_LEN-1);
-	memcpy(reason, smem_reason, size);
-	reason[size] = '\0';
-	pr_err("GSS subsystem failure reason: %s.\n", reason);
-
-	smem_reason[0] = '\0';
-	wmb();
-}
-
-static void restart_gss(void)
-{
-	log_gss_sfr();
-	subsystem_restart_dev(gss_8064_dev);
-}
-
-static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
-{
-	/* Ignore if we're the one that set SMSM_RESET */
-	if (crash_shutdown)
-		return;
-
-	if (new_state & SMSM_RESET) {
-		pr_err("GSS SMSM state changed to SMSM_RESET.\n"
-			"Probable err_fatal on the GSS. "
-			"Calling subsystem restart...\n");
-		restart_gss();
-	}
-}
-
-#define Q6_FW_WDOG_ENABLE		0x08882024
-#define Q6_SW_WDOG_ENABLE		0x08982024
-static int gss_shutdown(const struct subsys_desc *desc)
-{
-	pil_force_shutdown("gss");
-	disable_irq_nosync(GSS_A5_WDOG_EXPIRED);
-
-	return 0;
-}
-
-static int gss_powerup(const struct subsys_desc *desc)
-{
-	pil_force_boot("gss");
-	enable_irq(GSS_A5_WDOG_EXPIRED);
-	return 0;
-}
-
-void gss_crash_shutdown(const struct subsys_desc *desc)
-{
-	crash_shutdown = 1;
-	smsm_reset_modem(SMSM_RESET);
-}
-
-/* FIXME: Get address, size from PIL */
-static struct ramdump_segment gss_segments[] = {
-	{0x89000000, 0x00D00000}
-};
-
-static struct ramdump_segment smem_segments[] = {
-	{0x80000000, 0x00200000},
-};
-
-static int gss_ramdump(int enable,
-				const struct subsys_desc *crashed_subsys)
-{
-	int ret = 0;
-
-	if (enable) {
-		ret = do_ramdump(gss_data.gss_ramdump_dev, gss_segments,
-			ARRAY_SIZE(gss_segments));
-
-		if (ret < 0) {
-			pr_err("Unable to dump gss memory (rc = %d).\n",
-			       ret);
-			goto out;
-		}
-
-		ret = do_ramdump(gss_data.smem_ramdump_dev, smem_segments,
-			ARRAY_SIZE(smem_segments));
-
-		if (ret < 0) {
-			pr_err("Unable to dump smem memory (rc = %d).\n", ret);
-			goto out;
-		}
-	}
-
-out:
-	return ret;
-}
-
-static irqreturn_t gss_wdog_bite_irq(int irq, void *dev_id)
-{
-	pr_err("Watchdog bite received from GSS!\n");
-	restart_gss();
-
-	return IRQ_HANDLED;
-}
-
-static struct subsys_desc gss_8064 = {
-	.name = "gss",
-	.shutdown = gss_shutdown,
-	.powerup = gss_powerup,
-	.ramdump = gss_ramdump,
-	.crash_shutdown = gss_crash_shutdown
-};
-
-static int gss_subsystem_restart_init(void)
-{
-	gss_8064_dev = subsys_register(&gss_8064);
-	if (IS_ERR(gss_8064_dev))
-		return PTR_ERR(gss_8064_dev);
-	return 0;
-}
-
-static int gss_open(struct inode *inode, struct file *filep)
-{
-	void *ret;
-	gss_data.pil_handle = ret = pil_get("gss");
-	if (!ret)
-		pr_debug("%s - pil_get returned NULL\n", __func__);
-	return 0;
-}
-
-static int gss_release(struct inode *inode, struct file *filep)
-{
-	pil_put(gss_data.pil_handle);
-	pr_debug("%s pil_put called on GSS\n", __func__);
-	return 0;
-}
-
-const struct file_operations gss_file_ops = {
-	.open = gss_open,
-	.release = gss_release,
-};
-
-static int __init gss_8064_init(void)
-{
-	int ret;
-
-	if (!(cpu_is_apq8064() || cpu_is_apq8064ab()))
-		return -ENODEV;
-
-	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
-		smsm_state_cb, 0);
-
-	if (ret < 0)
-		pr_err("%s: Unable to register SMSM callback! (%d)\n",
-				__func__, ret);
-
-	ret = request_irq(GSS_A5_WDOG_EXPIRED, gss_wdog_bite_irq,
-			IRQF_TRIGGER_RISING, "gss_a5_wdog", NULL);
-
-	if (ret < 0) {
-		pr_err("%s: Unable to request gss watchdog IRQ. (%d)\n",
-				__func__, ret);
-		disable_irq_nosync(GSS_A5_WDOG_EXPIRED);
-		goto out;
-	}
-
-	ret = gss_subsystem_restart_init();
-
-	if (ret < 0) {
-		pr_err("%s: Unable to reg with subsystem restart. (%d)\n",
-				__func__, ret);
-		goto out;
-	}
-
-	gss_data.gss_dev.minor = MISC_DYNAMIC_MINOR;
-	gss_data.gss_dev.name = "gss";
-	gss_data.gss_dev.fops = &gss_file_ops;
-	ret = misc_register(&gss_data.gss_dev);
-
-	if (ret) {
-		pr_err("%s: misc_registers failed for %s (%d)", __func__,
-				gss_data.gss_dev.name, ret);
-		goto out;
-	}
-
-	gss_data.gss_ramdump_dev = create_ramdump_device("gss");
-
-	if (!gss_data.gss_ramdump_dev) {
-		pr_err("%s: Unable to create gss ramdump device. (%d)\n",
-				__func__, -ENOMEM);
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	gss_data.smem_ramdump_dev = create_ramdump_device("smem-gss");
-
-	if (!gss_data.smem_ramdump_dev) {
-		pr_err("%s: Unable to create smem ramdump device. (%d)\n",
-				__func__, -ENOMEM);
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	pr_info("%s: gss fatal driver init'ed.\n", __func__);
-out:
-	return ret;
-}
-
-module_init(gss_8064_init);
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs.h b/arch/arm/mach-msm/include/mach/msm_dcvs.h
index fa7e6f0..78d0d4a 100644
--- a/arch/arm/mach-msm/include/mach/msm_dcvs.h
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -18,6 +18,8 @@
 #define CORE_NAME_MAX (32)
 #define CORES_MAX (10)
 
+#define CPU_OFFSET	1  /* used to notify TZ the core number */
+
 enum msm_core_idle_state {
 	MSM_DCVS_IDLE_ENTER,
 	MSM_DCVS_IDLE_EXIT,
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
index 3cc2595..d97cd32 100644
--- a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,13 +13,23 @@
 #ifndef _ARCH_ARM_MACH_MSM_MSM_DCVS_SCM_H
 #define _ARCH_ARM_MACH_MSM_MSM_DCVS_SCM_H
 
+enum msm_dcvs_algo_param_type {
+	MSM_DCVS_ALGO_DCVS_PARAM = 0,
+	MSM_DCVS_ALGO_MPD_PARAM  = 1,
+};
+
 enum msm_dcvs_scm_event {
-	MSM_DCVS_SCM_IDLE_ENTER,
-	MSM_DCVS_SCM_IDLE_EXIT,
-	MSM_DCVS_SCM_QOS_TIMER_EXPIRED,
-	MSM_DCVS_SCM_CLOCK_FREQ_UPDATE,
-	MSM_DCVS_SCM_ENABLE_CORE,
-	MSM_DCVS_SCM_RESET_CORE,
+	MSM_DCVS_SCM_IDLE_ENTER = 0, /* Core enters idle */
+	MSM_DCVS_SCM_IDLE_EXIT = 1, /* Core exits idle */
+	MSM_DCVS_SCM_QOS_TIMER_EXPIRED = 2, /* Core slack timer expired */
+	MSM_DCVS_SCM_CLOCK_FREQ_UPDATE = 3, /* Core freq change complete */
+	MSM_DCVS_SCM_CORE_ONLINE = 4, /* Core is online */
+	MSM_DCVS_SCM_CORE_OFFLINE = 5, /* Core is offline */
+	MSM_DCVS_SCM_CORE_UNAVAILABLE = 6, /* Core is offline + unavailable */
+	MSM_DCVS_SCM_DCVS_ENABLE = 7, /* DCVS is enabled/disabled for core */
+	MSM_DCVS_SCM_MPD_ENABLE = 8, /* Enable/disable MP Decision */
+	MSM_DCVS_SCM_RUNQ_UPDATE = 9, /* Update running threads */
+	MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED = 10, /* MPDecision slack timer */
 };
 
 struct msm_dcvs_algo_param {
@@ -46,6 +56,18 @@
 };
 
 
+struct msm_mpd_algo_param {
+	uint32_t em_win_size_min_us;
+	uint32_t em_win_size_max_us;
+	uint32_t em_max_util_pct;
+	uint32_t mp_em_rounding_point_min;
+	uint32_t mp_em_rounding_point_max;
+	uint32_t online_util_pct_min;
+	uint32_t online_util_pct_max;
+	uint32_t slack_time_min_us;
+	uint32_t slack_time_max_us;
+};
+
 #ifdef CONFIG_MSM_DCVS
 /**
  * Initialize DCVS algorithm in TrustZone.
@@ -101,6 +123,15 @@
 		struct msm_dcvs_algo_param *param);
 
 /**
+ * Set MPDecision algorithm parameters
+ *
+ * @param: The param data structure
+ *	0 on success.
+ *	-EINVAL: Invalid args.
+ */
+extern int msm_mpd_scm_set_algo_params(struct msm_mpd_algo_param *param);
+
+/**
  * Do an SCM call.
  *
  * @core_id: The core identifier.
@@ -158,6 +189,9 @@
 static inline int msm_dcvs_scm_set_algo_params(uint32_t core_id,
 		struct msm_dcvs_algo_param *param)
 { return -ENOSYS; }
+static inline int msm_mpd_scm_set_algo_params(
+		struct msm_mpd_algo_param *param)
+{ return -ENOSYS; }
 static inline int msm_dcvs_scm_event(uint32_t core_id,
 		enum msm_dcvs_scm_event event_id,
 		uint32_t param0, uint32_t param1,
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index eecdd67..765de13 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -34,9 +34,27 @@
 #define MSM9625_TLMM_PHYS	0xFD510000
 #define MSM9625_TLMM_SIZE	SZ_16K
 
+/*
+ * TODO: Revert IMEM_PHYS back to actual
+ * address 0xfe807800
+ * after IMEM issues resolved.
+ *
+ */
+#define MSM9625_IMEM_PHYS	0xFC42B000
+#define MSM9625_IMEM_SIZE	SZ_2K
+
 #ifdef CONFIG_DEBUG_MSM9625_UART
 #define MSM_DEBUG_UART_BASE	IOMEM(0xFA71E000)
 #define MSM_DEBUG_UART_PHYS	0xF991E000
 #endif
 
+/*
+ * IMEM is retained for secure watchdog reset
+ * Debug Image looks at actual IMEM to
+ * do memory dumping.
+ */
+
+#define MSM9625_DBG_IMEM_PHYS	0xFE807800
+#define MSM9625_DBG_IMEM_SIZE	SZ_4K
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
index f6e082d..075d20f 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -32,7 +32,8 @@
 	RPM_VREG_VERSION_9615,
 	RPM_VREG_VERSION_8930,
 	RPM_VREG_VERSION_8930_PM8917,
-	RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_8930_PM8917,
+	RPM_VREG_VERSION_8960_PM8917,
+	RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_8960_PM8917,
 };
 
 #define RPM_VREG_PIN_CTRL_NONE		0x00
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 5ee7068..39ac253 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -462,6 +462,7 @@
 	MSM_CHIP_DEVICE(APCS_GCC, MSM9625),
 	MSM_CHIP_DEVICE(TLMM, MSM9625),
 	MSM_CHIP_DEVICE(TMR, MSM9625),
+	MSM_CHIP_DEVICE(IMEM, MSM9625),
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
 		.length =   MSM_SHARED_RAM_SIZE,
@@ -470,6 +471,7 @@
 #ifdef CONFIG_DEBUG_MSM9625_UART
 	MSM_DEVICE(DEBUG_UART),
 #endif
+	MSM_CHIP_DEVICE(DBG_IMEM, MSM9625),
 };
 
 void __init msm_map_msm9625_io(void)
diff --git a/arch/arm/mach-msm/lpass-8660.c b/arch/arm/mach-msm/lpass-8660.c
deleted file mode 100644
index be18b68..0000000
--- a/arch/arm/mach-msm/lpass-8660.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. 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/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/err.h>
-
-#include <mach/irqs.h>
-#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-
-#include "smd_private.h"
-#include "modem_notifier.h"
-#include "ramdump.h"
-
-#define Q6SS_WDOG_ENABLE		0x28882024
-#define Q6SS_SOFT_INTR_WAKEUP		0x288A001C
-#define MODULE_NAME			"lpass_8x60"
-#define SCM_Q6_NMI_CMD			0x1
-
-static struct subsys_device *subsys_8x60_q6_dev;
-
-/* Subsystem restart: QDSP6 data, functions */
-static void *q6_ramdump_dev;
-static void q6_fatal_fn(struct work_struct *);
-static DECLARE_WORK(q6_fatal_work, q6_fatal_fn);
-static void __iomem *q6_wakeup_intr;
-
-static void q6_fatal_fn(struct work_struct *work)
-{
-	pr_err("%s: Watchdog bite received from Q6!\n", MODULE_NAME);
-	subsystem_restart_dev(subsys_8x60_q6_dev);
-	enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
-}
-
-static void send_q6_nmi(void)
-{
-	/* Send NMI to QDSP6 via an SCM call. */
-	scm_call_atomic1(SCM_SVC_UTIL, SCM_Q6_NMI_CMD, 0x1);
-
-	/* Wakeup the Q6 */
-	if (q6_wakeup_intr)
-		writel_relaxed(0x2000, q6_wakeup_intr);
-	else
-		pr_warn("lpass-8660: Unable to send wakeup interrupt to Q6.\n");
-
-	/* Q6 requires atleast 100ms to dump caches etc.*/
-	mdelay(100);
-
-	pr_info("subsystem-fatal-8x60: Q6 NMI was sent.\n");
-}
-
-int subsys_q6_shutdown(const struct subsys_desc *crashed_subsys)
-{
-	void __iomem *q6_wdog_addr =
-		ioremap_nocache(Q6SS_WDOG_ENABLE, 8);
-
-	send_q6_nmi();
-	writel_relaxed(0x0, q6_wdog_addr);
-	/* The write needs to go through before the q6 is shutdown. */
-	mb();
-	iounmap(q6_wdog_addr);
-
-	pil_force_shutdown("q6");
-	disable_irq_nosync(LPASS_Q6SS_WDOG_EXPIRED);
-
-	return 0;
-}
-
-int subsys_q6_powerup(const struct subsys_desc *crashed_subsys)
-{
-	int ret = pil_force_boot("q6");
-	enable_irq(LPASS_Q6SS_WDOG_EXPIRED);
-	return ret;
-}
-
-/* FIXME: Get address, size from PIL */
-static struct ramdump_segment q6_segments[] = { {0x46700000, 0x47F00000 -
-					0x46700000}, {0x28400000, 0x12800} };
-static int subsys_q6_ramdump(int enable,
-				const struct subsys_desc *crashed_subsys)
-{
-	if (enable)
-		return do_ramdump(q6_ramdump_dev, q6_segments,
-				ARRAY_SIZE(q6_segments));
-	else
-		return 0;
-}
-
-void subsys_q6_crash_shutdown(const struct subsys_desc *crashed_subsys)
-{
-	send_q6_nmi();
-}
-
-static irqreturn_t lpass_wdog_bite_irq(int irq, void *dev_id)
-{
-	int ret;
-
-	ret = schedule_work(&q6_fatal_work);
-	disable_irq_nosync(LPASS_Q6SS_WDOG_EXPIRED);
-
-	return IRQ_HANDLED;
-}
-
-static struct subsys_desc subsys_8x60_q6 = {
-	.name = "lpass",
-	.shutdown = subsys_q6_shutdown,
-	.powerup = subsys_q6_powerup,
-	.ramdump = subsys_q6_ramdump,
-	.crash_shutdown = subsys_q6_crash_shutdown
-};
-
-static void __exit lpass_fatal_exit(void)
-{
-	subsys_unregister(subsys_8x60_q6_dev);
-	iounmap(q6_wakeup_intr);
-	free_irq(LPASS_Q6SS_WDOG_EXPIRED, NULL);
-}
-
-static int __init lpass_fatal_init(void)
-{
-	int ret;
-
-	ret = request_irq(LPASS_Q6SS_WDOG_EXPIRED, lpass_wdog_bite_irq,
-			IRQF_TRIGGER_RISING, "q6_wdog", NULL);
-
-	if (ret < 0) {
-		pr_err("%s: Unable to request LPASS_Q6SS_WDOG_EXPIRED irq.",
-			__func__);
-		goto out;
-	}
-
-	q6_ramdump_dev = create_ramdump_device("lpass");
-
-	if (!q6_ramdump_dev) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	q6_wakeup_intr = ioremap_nocache(Q6SS_SOFT_INTR_WAKEUP, 8);
-
-	if (!q6_wakeup_intr)
-		pr_warn("lpass-8660: Unable to ioremap q6 wakeup address.");
-
-	subsys_8x60_q6_dev = subsys_register(&subsys_8x60_q6);
-	if (IS_ERR(subsys_8x60_q6_dev))
-		ret = PTR_ERR(subsys_8x60_q6_dev);
-out:
-	return ret;
-}
-
-module_init(lpass_fatal_init);
-module_exit(lpass_fatal_exit);
-
diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c
index 0c158de..890e450 100644
--- a/arch/arm/mach-msm/msm_dcvs.c
+++ b/arch/arm/mach-msm/msm_dcvs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -582,7 +582,7 @@
 	if (core->idle_driver) {
 		core->actual_freq = core->freq_driver->get_frequency(drv);
 		/* Notify TZ to start receiving idle info for the core */
-		ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 1,
+		ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 1,
 					   &ret1, &ret2);
 		core->idle_driver->enable(core->idle_driver,
 				MSM_DCVS_ENABLE_IDLE_PULSE);
@@ -615,7 +615,7 @@
 		core->idle_driver->enable(core->idle_driver,
 				MSM_DCVS_DISABLE_IDLE_PULSE);
 		/* Notify TZ to stop receiving idle info for the core */
-		ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 0,
+		ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 0,
 					   &ret1, &ret2);
 		hrtimer_cancel(&core->timer);
 		core->idle_driver->enable(core->idle_driver,
diff --git a/arch/arm/mach-msm/msm_dcvs_scm.c b/arch/arm/mach-msm/msm_dcvs_scm.c
index 6095e0813..bf623df 100644
--- a/arch/arm/mach-msm/msm_dcvs_scm.c
+++ b/arch/arm/mach-msm/msm_dcvs_scm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -44,6 +44,14 @@
 	uint32_t size;
 };
 
+struct msm_algo_param {
+	enum msm_dcvs_algo_param_type		type;
+	union {
+		struct msm_dcvs_algo_param	dcvs_param;
+		struct msm_mpd_algo_param	mpd_param;
+	} u;
+};
+
 int msm_dcvs_scm_init(size_t size)
 {
 	int ret = 0;
@@ -123,13 +131,15 @@
 {
 	int ret = 0;
 	struct scm_algo algo;
-	struct msm_dcvs_algo_param *p = NULL;
+	struct msm_algo_param *p = NULL;
 
-	p = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_algo_param)), GFP_KERNEL);
+	p = kzalloc(PAGE_ALIGN(sizeof(struct msm_algo_param)), GFP_KERNEL);
 	if (!p)
 		return -ENOMEM;
 
-	memcpy(p, param, sizeof(struct msm_dcvs_algo_param));
+
+	p->type = MSM_DCVS_ALGO_DCVS_PARAM;
+	memcpy(&p->u.dcvs_param, param, sizeof(struct msm_dcvs_algo_param));
 
 	algo.core_id = core_id;
 	algo.algo_phy = virt_to_phys(p);
@@ -143,6 +153,31 @@
 }
 EXPORT_SYMBOL(msm_dcvs_scm_set_algo_params);
 
+int msm_mpd_scm_set_algo_params(struct msm_mpd_algo_param *param)
+{
+	int ret = 0;
+	struct scm_algo algo;
+	struct msm_algo_param *p = NULL;
+
+	p = kzalloc(PAGE_ALIGN(sizeof(struct msm_algo_param)), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	p->type = MSM_DCVS_ALGO_MPD_PARAM;
+	memcpy(&p->u.mpd_param, param, sizeof(struct msm_mpd_algo_param));
+
+	algo.core_id = 0;
+	algo.algo_phy = virt_to_phys(p);
+
+	ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_SET_ALGO_PARAM,
+			&algo, sizeof(algo), NULL, 0);
+
+	kfree(p);
+
+	return ret;
+}
+EXPORT_SYMBOL(msm_mpd_scm_set_algo_params);
+
 int msm_dcvs_scm_event(uint32_t core_id,
 		enum msm_dcvs_scm_event event_id,
 		uint32_t param0, uint32_t param1,
diff --git a/arch/arm/mach-msm/msm_mpdecision.c b/arch/arm/mach-msm/msm_mpdecision.c
new file mode 100644
index 0000000..056e4eb
--- /dev/null
+++ b/arch/arm/mach-msm/msm_mpdecision.c
@@ -0,0 +1,707 @@
+ /* Copyright (c) 2012, 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)     "mpd %s: " fmt, __func__
+
+#include <linux/cpumask.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/kobject.h>
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/cpu.h>
+#include <linux/stringify.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/cpu_pm.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/sched.h>
+#include <linux/rq_stats.h>
+#include <asm/atomic.h>
+#include <asm/page.h>
+#include <mach/msm_dcvs.h>
+#include <mach/msm_dcvs_scm.h>
+
+#define DEFAULT_RQ_AVG_POLL_MS    (1)
+
+struct mpd_attrib {
+	struct kobj_attribute	enabled;
+	struct kobj_attribute	rq_avg_poll_ms;
+	struct kobj_attribute iowait_threshold_pct;
+
+	struct kobj_attribute	em_win_size_min_us;
+	struct kobj_attribute	em_win_size_max_us;
+	struct kobj_attribute	em_max_util_pct;
+	struct kobj_attribute	mp_em_rounding_point_min;
+	struct kobj_attribute	mp_em_rounding_point_max;
+	struct kobj_attribute	online_util_pct_min;
+	struct kobj_attribute	online_util_pct_max;
+	struct kobj_attribute	slack_time_min_us;
+	struct kobj_attribute	slack_time_max_us;
+	struct kobj_attribute	hp_up_max_ms;
+	struct kobj_attribute	hp_up_ms;
+	struct kobj_attribute	hp_up_count;
+	struct kobj_attribute	hp_dw_max_ms;
+	struct kobj_attribute	hp_dw_ms;
+	struct kobj_attribute	hp_dw_count;
+	struct attribute_group	attrib_group;
+};
+
+struct msm_mpd_scm_data {
+	enum msm_dcvs_scm_event event;
+	int			nr;
+};
+
+struct mpdecision {
+	uint32_t			enabled;
+	atomic_t			algo_cpu_mask;
+	uint32_t			rq_avg_poll_ms;
+	uint32_t			iowait_threshold_pct;
+	ktime_t				next_update;
+	uint32_t			slack_us;
+	struct msm_mpd_algo_param	mp_param;
+	struct mpd_attrib		attrib;
+	struct mutex			lock;
+	struct task_struct		*task;
+	struct task_struct		*hptask;
+	struct hrtimer			slack_timer;
+	struct msm_mpd_scm_data		data;
+	int				hpupdate;
+	wait_queue_head_t		wait_q;
+	wait_queue_head_t		wait_hpq;
+};
+
+struct hp_latency {
+	int hp_up_max_ms;
+	int hp_up_ms;
+	int hp_up_count;
+	int hp_dw_max_ms;
+	int hp_dw_ms;
+	int hp_dw_count;
+};
+
+static DEFINE_PER_CPU(struct hrtimer, rq_avg_poll_timer);
+static DEFINE_SPINLOCK(rq_avg_lock);
+
+enum {
+	MSM_MPD_DEBUG_NOTIFIER = BIT(0),
+	MSM_MPD_CORE_STATUS = BIT(1),
+	MSM_MPD_SLACK_TIMER = BIT(2),
+};
+
+enum {
+	HPUPDATE_WAITING = 0, /* we are waiting for cpumask update */
+	HPUPDATE_SCHEDULED = 1, /* we are in the process of hotplugging */
+	HPUPDATE_IN_PROGRESS = 2, /* we are in the process of hotplugging */
+};
+
+static int msm_mpd_enabled = 1;
+module_param_named(enabled, msm_mpd_enabled, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static struct dentry *debugfs_base;
+static struct mpdecision msm_mpd;
+
+static struct hp_latency hp_latencies;
+
+static unsigned long last_nr;
+static int num_present_hundreds;
+
+#define RQ_AVG_INSIGNIFICANT_BITS	3
+static bool ok_to_update_tz(int nr, int last_nr)
+{
+	/*
+	 * Exclude unnecessary TZ reports if run queue haven't changed much from
+	 * the last reported value. The left shift by INSIGNIFICANT_BITS is to
+	 * filter out small changes in the run queue average which won't cause
+	 * a online cpu mask change. Also if the cpu online count does not match
+	 * the count requested by TZ and we are not in the process of bringing
+	 * cpus online as indicated by a HPUPDATE_IN_PROGRESS in msm_mpd.hpdata
+	 */
+	return
+	(((nr >> RQ_AVG_INSIGNIFICANT_BITS)
+				!= (last_nr >> RQ_AVG_INSIGNIFICANT_BITS))
+	|| ((hweight32(atomic_read(&msm_mpd.algo_cpu_mask))
+				!= num_online_cpus())
+		&& (msm_mpd.hpupdate != HPUPDATE_IN_PROGRESS)));
+}
+
+static enum hrtimer_restart msm_mpd_rq_avg_poll_timer(struct hrtimer *timer)
+{
+	int nr, nr_iowait;
+	ktime_t curr_time = ktime_get();
+	unsigned long flags;
+	int cpu = smp_processor_id();
+	enum hrtimer_restart restart = HRTIMER_RESTART;
+
+	spin_lock_irqsave(&rq_avg_lock, flags);
+	/* If running on the wrong cpu, don't restart */
+	if (&per_cpu(rq_avg_poll_timer, cpu) != timer)
+		restart = HRTIMER_NORESTART;
+
+	if (ktime_to_ns(ktime_sub(curr_time, msm_mpd.next_update)) < 0)
+		goto out;
+
+	msm_mpd.next_update = ktime_add_ns(curr_time,
+			(msm_mpd.rq_avg_poll_ms * NSEC_PER_MSEC));
+
+	sched_get_nr_running_avg(&nr, &nr_iowait);
+
+	if ((nr_iowait >= msm_mpd.iowait_threshold_pct) && (nr < last_nr))
+		nr = last_nr;
+
+	if (nr > num_present_hundreds)
+		nr = num_present_hundreds;
+
+	if (ok_to_update_tz(nr, last_nr)) {
+		hrtimer_try_to_cancel(&msm_mpd.slack_timer);
+		msm_mpd.data.nr = nr;
+		msm_mpd.data.event = MSM_DCVS_SCM_RUNQ_UPDATE;
+		wake_up(&msm_mpd.wait_q);
+		last_nr = nr;
+	}
+
+out:
+	hrtimer_set_expires(timer, msm_mpd.next_update);
+	spin_unlock_irqrestore(&rq_avg_lock, flags);
+	/* set next expiration */
+	return restart;
+}
+
+static void bring_up_cpu(int cpu)
+{
+	int cpu_action_time_ms;
+	int time_taken_ms;
+	int ret, ret1, ret2;
+
+	cpu_action_time_ms = ktime_to_ms(ktime_get());
+	ret = cpu_up(cpu);
+	if (ret) {
+		pr_debug("Error %d online core %d\n", ret, cpu);
+	} else {
+		time_taken_ms = ktime_to_ms(ktime_get()) - cpu_action_time_ms;
+		if (time_taken_ms > hp_latencies.hp_up_max_ms)
+			hp_latencies.hp_up_max_ms = time_taken_ms;
+		if (time_taken_ms > 5)
+			pr_warn("cpu_up for cpu%d exceeded 5ms (%d)\n",
+					cpu, time_taken_ms);
+		hp_latencies.hp_up_ms += time_taken_ms;
+		hp_latencies.hp_up_count++;
+		ret = msm_dcvs_scm_event(
+				CPU_OFFSET + cpu,
+				MSM_DCVS_SCM_CORE_ONLINE,
+				cpufreq_get(cpu),
+				(uint32_t) time_taken_ms * USEC_PER_MSEC,
+				&ret1, &ret2);
+		if (ret)
+			pr_err("Error sending hotplug scm event err=%d\n", ret);
+	}
+}
+
+static void bring_down_cpu(int cpu)
+{
+	int cpu_action_time_ms;
+	int time_taken_ms;
+	int ret, ret1, ret2;
+
+	BUG_ON(cpu == 0);
+	cpu_action_time_ms = ktime_to_ms(ktime_get());
+	ret = cpu_down(cpu);
+	if (ret) {
+		pr_debug("Error %d offline" "core %d\n", ret, cpu);
+	} else {
+		time_taken_ms = ktime_to_ms(ktime_get()) - cpu_action_time_ms;
+		if (time_taken_ms > hp_latencies.hp_dw_max_ms)
+			hp_latencies.hp_dw_max_ms = time_taken_ms;
+		if (time_taken_ms > 5)
+			pr_warn("cpu_down for cpu%d exceeded 5ms (%d)\n",
+						cpu, time_taken_ms);
+		hp_latencies.hp_dw_ms += time_taken_ms;
+		hp_latencies.hp_dw_count++;
+		ret = msm_dcvs_scm_event(
+				CPU_OFFSET + cpu,
+				MSM_DCVS_SCM_CORE_OFFLINE,
+				(uint32_t) time_taken_ms * USEC_PER_MSEC,
+				0,
+				&ret1, &ret2);
+		if (ret)
+			pr_err("Error sending hotplug scm event err=%d\n", ret);
+	}
+}
+
+static int __ref msm_mpd_update_scm(enum msm_dcvs_scm_event event, int nr)
+{
+	int ret = 0;
+	uint32_t req_cpu_mask = 0;
+	uint32_t slack_us = 0;
+	uint32_t param0 = 0;
+
+	if (event == MSM_DCVS_SCM_RUNQ_UPDATE)
+		param0 = nr;
+
+	ret = msm_dcvs_scm_event(0, event, param0, 0,
+				 &req_cpu_mask, &slack_us);
+
+	if (ret) {
+		pr_err("Error (%d) sending event %d, param %d\n", ret, event,
+				param0);
+		return ret;
+	}
+
+	msm_mpd.slack_us = slack_us;
+	atomic_set(&msm_mpd.algo_cpu_mask, req_cpu_mask);
+	msm_mpd.hpupdate = HPUPDATE_SCHEDULED;
+	wake_up(&msm_mpd.wait_hpq);
+
+	/* Start MP Decision slack timer */
+	if (slack_us) {
+		hrtimer_cancel(&msm_mpd.slack_timer);
+		ret = hrtimer_start(&msm_mpd.slack_timer,
+				ktime_set(0, slack_us * NSEC_PER_USEC),
+				HRTIMER_MODE_REL_PINNED);
+		if (ret)
+			pr_err("Failed to register slack timer (%d) %d\n",
+					slack_us, ret);
+	}
+
+	return ret;
+}
+
+static enum hrtimer_restart msm_mpd_slack_timer(struct hrtimer *timer)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rq_avg_lock, flags);
+	if (msm_mpd.data.event == MSM_DCVS_SCM_RUNQ_UPDATE)
+		goto out;
+
+	msm_mpd.data.nr = 0;
+	msm_mpd.data.event = MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED;
+	wake_up(&msm_mpd.wait_q);
+out:
+	spin_unlock_irqrestore(&rq_avg_lock, flags);
+	return HRTIMER_NORESTART;
+}
+
+static int msm_mpd_idle_notifier(struct notifier_block *self,
+				 unsigned long cmd, void *v)
+{
+	int cpu = smp_processor_id();
+	unsigned long flags;
+
+	switch (cmd) {
+	case CPU_PM_EXIT:
+		spin_lock_irqsave(&rq_avg_lock, flags);
+		hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu),
+			      msm_mpd.next_update,
+			      HRTIMER_MODE_ABS_PINNED);
+		spin_unlock_irqrestore(&rq_avg_lock, flags);
+		break;
+	case CPU_PM_ENTER:
+		hrtimer_cancel(&per_cpu(rq_avg_poll_timer, cpu));
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static int msm_mpd_hotplug_notifier(struct notifier_block *self,
+				    unsigned long action, void *hcpu)
+{
+	int cpu = (int)hcpu;
+	unsigned long flags;
+
+	switch (action & (~CPU_TASKS_FROZEN)) {
+	case CPU_STARTING:
+		spin_lock_irqsave(&rq_avg_lock, flags);
+		hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu),
+			      msm_mpd.next_update,
+			      HRTIMER_MODE_ABS_PINNED);
+		spin_unlock_irqrestore(&rq_avg_lock, flags);
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block msm_mpd_idle_nb = {
+	.notifier_call = msm_mpd_idle_notifier,
+};
+
+static struct notifier_block msm_mpd_hotplug_nb = {
+	.notifier_call = msm_mpd_hotplug_notifier,
+};
+
+static int __cpuinit msm_mpd_do_hotplug(void *data)
+{
+	int *event = (int *)data;
+	static struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
+	int cpu;
+
+	sched_setscheduler(current, SCHED_FIFO, &param);
+
+	while (1) {
+		wait_event(msm_mpd.wait_hpq, *event || kthread_should_stop());
+		if (kthread_should_stop())
+			break;
+
+		msm_mpd.hpupdate = HPUPDATE_IN_PROGRESS;
+		/*
+		 * Bring online any offline cores, then offline any online
+		 * cores.  Whenever a core is off/onlined restart the procedure
+		 * in case a new core is desired to be brought online in the
+		 * mean time.
+		 */
+restart:
+		for_each_possible_cpu(cpu) {
+			if ((atomic_read(&msm_mpd.algo_cpu_mask) & (1 << cpu))
+				&& !cpu_online(cpu)) {
+				bring_up_cpu(cpu);
+				if (cpu_online(cpu))
+					goto restart;
+			}
+		}
+
+		for_each_possible_cpu(cpu) {
+			if (!(atomic_read(&msm_mpd.algo_cpu_mask) & (1 << cpu))
+				&& cpu_online(cpu)) {
+				bring_down_cpu(cpu);
+				if (!cpu_online(cpu))
+					goto restart;
+			}
+		}
+		msm_mpd.hpupdate = HPUPDATE_WAITING;
+	}
+
+	return 0;
+}
+
+static int msm_mpd_do_update_scm(void *data)
+{
+	struct msm_mpd_scm_data *scm_data = (struct msm_mpd_scm_data *)data;
+	static struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
+	unsigned long flags;
+	enum msm_dcvs_scm_event event;
+	int nr;
+
+	sched_setscheduler(current, SCHED_FIFO, &param);
+
+	while (1) {
+		wait_event(msm_mpd.wait_q,
+			msm_mpd.data.event == MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED
+			|| msm_mpd.data.event == MSM_DCVS_SCM_RUNQ_UPDATE
+			|| kthread_should_stop());
+
+		if (kthread_should_stop())
+			break;
+
+		spin_lock_irqsave(&rq_avg_lock, flags);
+		event = scm_data->event;
+		nr = scm_data->nr;
+		scm_data->event = 0;
+		scm_data->nr = 0;
+		spin_unlock_irqrestore(&rq_avg_lock, flags);
+
+		msm_mpd_update_scm(event, nr);
+	}
+	return 0;
+}
+
+static int __ref msm_mpd_set_enabled(uint32_t enable)
+{
+	int ret = 0;
+	int ret0 = 0;
+	int ret1 = 0;
+	int cpu;
+	static uint32_t last_enable;
+
+	enable = (enable > 0) ? 1 : 0;
+	if (last_enable == enable)
+		return ret;
+
+	if (enable) {
+		ret = msm_mpd_scm_set_algo_params(&msm_mpd.mp_param);
+		if (ret) {
+			pr_err("Error(%d): msm_mpd_scm_set_algo_params failed\n",
+				ret);
+			return ret;
+		}
+	}
+
+	ret = msm_dcvs_scm_event(0, MSM_DCVS_SCM_MPD_ENABLE, enable, 0,
+			&ret0, &ret1);
+	if (ret) {
+		pr_err("Error(%d) %s MP Decision\n",
+				ret, (enable ? "enabling" : "disabling"));
+	} else {
+		last_enable = enable;
+		last_nr = 0;
+	}
+	if (enable) {
+		msm_mpd.next_update = ktime_add_ns(ktime_get(),
+				(msm_mpd.rq_avg_poll_ms * NSEC_PER_MSEC));
+		msm_mpd.task = kthread_run(msm_mpd_do_update_scm,
+					      &msm_mpd.data, "msm_mpdecision");
+		if (IS_ERR(msm_mpd.task))
+			return -EFAULT;
+
+		msm_mpd.hptask = kthread_run(msm_mpd_do_hotplug,
+						&msm_mpd.hpupdate, "msm_hp");
+		if (IS_ERR(msm_mpd.hptask))
+			return -EFAULT;
+
+		for_each_online_cpu(cpu)
+			hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu),
+				      msm_mpd.next_update,
+				      HRTIMER_MODE_ABS_PINNED);
+		cpu_pm_register_notifier(&msm_mpd_idle_nb);
+		register_cpu_notifier(&msm_mpd_hotplug_nb);
+		msm_mpd.enabled = 1;
+	} else {
+		for_each_online_cpu(cpu)
+			hrtimer_cancel(&per_cpu(rq_avg_poll_timer, cpu));
+		kthread_stop(msm_mpd.hptask);
+		kthread_stop(msm_mpd.task);
+		cpu_pm_unregister_notifier(&msm_mpd_idle_nb);
+		unregister_cpu_notifier(&msm_mpd_hotplug_nb);
+		msm_mpd.enabled = 0;
+	}
+
+	return ret;
+}
+
+static int msm_mpd_set_rq_avg_poll_ms(uint32_t val)
+{
+	/*
+	 * No need to do anything. Just let the timer set its own next poll
+	 * interval when it next fires.
+	 */
+	msm_mpd.rq_avg_poll_ms = val;
+	return 0;
+}
+
+static int msm_mpd_set_iowait_threshold_pct(uint32_t val)
+{
+	/*
+	 * No need to do anything. Just let the timer set its own next poll
+	 * interval when it next fires.
+	 */
+	msm_mpd.iowait_threshold_pct = val;
+	return 0;
+}
+
+#define MPD_ALGO_PARAM(_name, _param) \
+static ssize_t msm_mpd_attr_##_name##_show(struct kobject *kobj, \
+			struct kobj_attribute *attr, char *buf) \
+{ \
+	return snprintf(buf, PAGE_SIZE, "%d\n", _param); \
+} \
+static ssize_t msm_mpd_attr_##_name##_store(struct kobject *kobj, \
+		struct kobj_attribute *attr, const char *buf, size_t count) \
+{ \
+	int ret = 0; \
+	uint32_t val; \
+	uint32_t old_val; \
+	mutex_lock(&msm_mpd.lock); \
+	ret = kstrtouint(buf, 10, &val); \
+	if (ret) { \
+		pr_err("Invalid input %s for %s %d\n", \
+				buf, __stringify(_name), ret);\
+		return 0; \
+	} \
+	old_val = _param; \
+	_param = val; \
+	ret = msm_mpd_scm_set_algo_params(&msm_mpd.mp_param); \
+	if (ret) { \
+		pr_err("Error %d returned when setting algo param %s to %d\n",\
+				ret, __stringify(_name), val); \
+		_param = old_val; \
+	} \
+	mutex_unlock(&msm_mpd.lock); \
+	return count; \
+}
+
+#define MPD_PARAM(_name, _param) \
+static ssize_t msm_mpd_attr_##_name##_show(struct kobject *kobj, \
+			struct kobj_attribute *attr, char *buf) \
+{ \
+	return snprintf(buf, PAGE_SIZE, "%d\n", _param); \
+} \
+static ssize_t msm_mpd_attr_##_name##_store(struct kobject *kobj, \
+		struct kobj_attribute *attr, const char *buf, size_t count) \
+{ \
+	int ret = 0; \
+	uint32_t val; \
+	uint32_t old_val; \
+	mutex_lock(&msm_mpd.lock); \
+	ret = kstrtouint(buf, 10, &val); \
+	if (ret) { \
+		pr_err("Invalid input %s for %s %d\n", \
+				buf, __stringify(_name), ret);\
+		return 0; \
+	} \
+	old_val = _param; \
+	ret = msm_mpd_set_##_name(val); \
+	if (ret) { \
+		pr_err("Error %d returned when setting algo param %s to %d\n",\
+				ret, __stringify(_name), val); \
+		_param = old_val; \
+	} \
+	mutex_unlock(&msm_mpd.lock); \
+	return count; \
+}
+
+#define MPD_RW_ATTRIB(i, _name) \
+	msm_mpd.attrib._name.attr.name = __stringify(_name); \
+	msm_mpd.attrib._name.attr.mode = S_IRUGO | S_IWUSR; \
+	msm_mpd.attrib._name.show = msm_mpd_attr_##_name##_show; \
+	msm_mpd.attrib._name.store = msm_mpd_attr_##_name##_store; \
+	msm_mpd.attrib.attrib_group.attrs[i] = &msm_mpd.attrib._name.attr;
+
+MPD_PARAM(enabled, msm_mpd.enabled);
+MPD_PARAM(rq_avg_poll_ms, msm_mpd.rq_avg_poll_ms);
+MPD_PARAM(iowait_threshold_pct, msm_mpd.iowait_threshold_pct);
+MPD_ALGO_PARAM(em_win_size_min_us, msm_mpd.mp_param.em_win_size_min_us);
+MPD_ALGO_PARAM(em_win_size_max_us, msm_mpd.mp_param.em_win_size_max_us);
+MPD_ALGO_PARAM(em_max_util_pct, msm_mpd.mp_param.em_max_util_pct);
+MPD_ALGO_PARAM(mp_em_rounding_point_min,
+				msm_mpd.mp_param.mp_em_rounding_point_min);
+MPD_ALGO_PARAM(mp_em_rounding_point_max,
+				msm_mpd.mp_param.mp_em_rounding_point_max);
+MPD_ALGO_PARAM(online_util_pct_min, msm_mpd.mp_param.online_util_pct_min);
+MPD_ALGO_PARAM(online_util_pct_max, msm_mpd.mp_param.online_util_pct_max);
+MPD_ALGO_PARAM(slack_time_min_us, msm_mpd.mp_param.slack_time_min_us);
+MPD_ALGO_PARAM(slack_time_max_us, msm_mpd.mp_param.slack_time_max_us);
+MPD_ALGO_PARAM(hp_up_max_ms, hp_latencies.hp_up_max_ms);
+MPD_ALGO_PARAM(hp_up_ms, hp_latencies.hp_up_ms);
+MPD_ALGO_PARAM(hp_up_count, hp_latencies.hp_up_count);
+MPD_ALGO_PARAM(hp_dw_max_ms, hp_latencies.hp_dw_max_ms);
+MPD_ALGO_PARAM(hp_dw_ms, hp_latencies.hp_dw_ms);
+MPD_ALGO_PARAM(hp_dw_count, hp_latencies.hp_dw_count);
+
+static int __devinit msm_mpd_probe(struct platform_device *pdev)
+{
+	struct kobject *module_kobj = NULL;
+	int ret = 0;
+	const int attr_count = 19;
+	struct msm_mpd_algo_param *param = NULL;
+
+	param = pdev->dev.platform_data;
+
+	module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+	if (!module_kobj) {
+		pr_err("Cannot find kobject for module %s\n", KBUILD_MODNAME);
+		ret = -ENOENT;
+		goto done;
+	}
+
+	msm_mpd.attrib.attrib_group.attrs =
+		kzalloc(attr_count * sizeof(struct attribute *), GFP_KERNEL);
+	if (!msm_mpd.attrib.attrib_group.attrs) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	MPD_RW_ATTRIB(0, enabled);
+	MPD_RW_ATTRIB(1, rq_avg_poll_ms);
+	MPD_RW_ATTRIB(2, iowait_threshold_pct);
+	MPD_RW_ATTRIB(3, em_win_size_min_us);
+	MPD_RW_ATTRIB(4, em_win_size_max_us);
+	MPD_RW_ATTRIB(5, em_max_util_pct);
+	MPD_RW_ATTRIB(6, mp_em_rounding_point_min);
+	MPD_RW_ATTRIB(7, mp_em_rounding_point_max);
+	MPD_RW_ATTRIB(8, online_util_pct_min);
+	MPD_RW_ATTRIB(9, online_util_pct_max);
+	MPD_RW_ATTRIB(10, slack_time_min_us);
+	MPD_RW_ATTRIB(11, slack_time_max_us);
+	MPD_RW_ATTRIB(12, hp_up_max_ms);
+	MPD_RW_ATTRIB(13, hp_up_ms);
+	MPD_RW_ATTRIB(14, hp_up_count);
+	MPD_RW_ATTRIB(15, hp_dw_max_ms);
+	MPD_RW_ATTRIB(16, hp_dw_ms);
+	MPD_RW_ATTRIB(17, hp_dw_count);
+
+	msm_mpd.attrib.attrib_group.attrs[18] = NULL;
+	ret = sysfs_create_group(module_kobj, &msm_mpd.attrib.attrib_group);
+	if (ret)
+		pr_err("Unable to create sysfs objects :%d\n", ret);
+
+	msm_mpd.rq_avg_poll_ms = DEFAULT_RQ_AVG_POLL_MS;
+
+	memcpy(&msm_mpd.mp_param, param, sizeof(struct msm_mpd_algo_param));
+
+	debugfs_base = debugfs_create_dir("msm_mpdecision", NULL);
+	if (!debugfs_base) {
+		pr_err("Cannot create debugfs base msm_mpdecision\n");
+		ret = -ENOENT;
+		goto done;
+	}
+
+done:
+	if (ret && debugfs_base)
+		debugfs_remove(debugfs_base);
+
+	return ret;
+}
+
+static int __devexit msm_mpd_remove(struct platform_device *pdev)
+{
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver msm_mpd_driver = {
+	.probe	= msm_mpd_probe,
+	.remove	= __devexit_p(msm_mpd_remove),
+	.driver	= {
+		.name	= "msm_mpdecision",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init msm_mpdecision_init(void)
+{
+	int cpu;
+	if (!msm_mpd_enabled) {
+		pr_info("Not enabled\n");
+		return 0;
+	}
+
+	num_present_hundreds = 100 * num_present_cpus();
+
+	hrtimer_init(&msm_mpd.slack_timer, CLOCK_MONOTONIC,
+			HRTIMER_MODE_REL_PINNED);
+	msm_mpd.slack_timer.function = msm_mpd_slack_timer;
+
+	for_each_possible_cpu(cpu) {
+		hrtimer_init(&per_cpu(rq_avg_poll_timer, cpu),
+			     CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
+		per_cpu(rq_avg_poll_timer, cpu).function
+				= msm_mpd_rq_avg_poll_timer;
+	}
+	mutex_init(&msm_mpd.lock);
+	init_waitqueue_head(&msm_mpd.wait_q);
+	init_waitqueue_head(&msm_mpd.wait_hpq);
+	return platform_driver_register(&msm_mpd_driver);
+}
+late_initcall(msm_mpdecision_init);
diff --git a/arch/arm/mach-msm/peripheral-loader.h b/arch/arm/mach-msm/peripheral-loader.h
index e3b250b..405b73f 100644
--- a/arch/arm/mach-msm/peripheral-loader.h
+++ b/arch/arm/mach-msm/peripheral-loader.h
@@ -55,7 +55,15 @@
 
 struct pil_device;
 
+#ifdef CONFIG_MSM_PIL
 extern struct pil_device *msm_pil_register(struct pil_desc *desc);
 extern void msm_pil_unregister(struct pil_device *pil);
+#else
+static inline struct pil_device *msm_pil_register(struct pil_desc *desc)
+{
+	return NULL;
+}
+static inline void msm_pil_unregister(struct pil_device *pil) { }
+#endif
 
 #endif
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index 73248db..bccbce2 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -21,15 +21,22 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/smp.h>
+#include <linux/miscdevice.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
 
 #include <mach/msm_iomap.h>
 #include <mach/msm_xo.h>
 #include <mach/socinfo.h>
 #include <mach/msm_bus_board.h>
 #include <mach/msm_bus.h>
+#include <mach/subsystem_restart.h>
+#include <mach/peripheral-loader.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
+#include "smd_private.h"
+#include "ramdump.h"
 
 #define GSS_CSR_AHB_CLK_SEL	0x0
 #define GSS_CSR_RESET		0x4
@@ -63,6 +70,14 @@
 	unsigned long start_addr;
 	struct clk *xo;
 	struct pil_device *pil;
+	struct miscdevice misc_dev;
+	struct subsys_device *subsys;
+	struct subsys_desc subsys_desc;
+	int crash_shutdown;
+	int irq;
+	void *pil_handle;
+	struct ramdump_device *ramdump_dev;
+	struct ramdump_device *smem_ramdump_dev;
 };
 
 static int pil_gss_init_image(struct pil_desc *pil, const u8 *metadata,
@@ -308,11 +323,160 @@
 	.proxy_unvote = remove_gss_proxy_votes,
 };
 
+#define MAX_SSR_REASON_LEN 81U
+
+static void log_gss_sfr(void)
+{
+	u32 size;
+	char *smem_reason, reason[MAX_SSR_REASON_LEN];
+
+	smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
+	if (!smem_reason || !size) {
+		pr_err("GSS subsystem failure reason: (unknown, smem_get_entry failed).\n");
+		return;
+	}
+	if (!smem_reason[0]) {
+		pr_err("GSS subsystem failure reason: (unknown, init string found).\n");
+		return;
+	}
+
+	size = min(size, MAX_SSR_REASON_LEN-1);
+	memcpy(reason, smem_reason, size);
+	reason[size] = '\0';
+	pr_err("GSS subsystem failure reason: %s.\n", reason);
+
+	smem_reason[0] = '\0';
+	wmb();
+}
+
+static void restart_gss(struct gss_data *drv)
+{
+	log_gss_sfr();
+	subsystem_restart_dev(drv->subsys);
+}
+
+static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
+{
+	struct gss_data *drv = data;
+
+	/* Ignore if we're the one that set SMSM_RESET */
+	if (drv->crash_shutdown)
+		return;
+
+	if (new_state & SMSM_RESET) {
+		pr_err("GSS SMSM state changed to SMSM_RESET.\n"
+			"Probable err_fatal on the GSS. "
+			"Calling subsystem restart...\n");
+		restart_gss(drv);
+	}
+}
+
+static int gss_shutdown(const struct subsys_desc *desc)
+{
+	struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
+
+	pil_force_shutdown("gss");
+	disable_irq_nosync(drv->irq);
+
+	return 0;
+}
+
+static int gss_powerup(const struct subsys_desc *desc)
+{
+	struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
+
+	pil_force_boot("gss");
+	enable_irq(drv->irq);
+	return 0;
+}
+
+void gss_crash_shutdown(const struct subsys_desc *desc)
+{
+	struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
+
+	drv->crash_shutdown = 1;
+	smsm_reset_modem(SMSM_RESET);
+}
+
+/* FIXME: Get address, size from PIL */
+static struct ramdump_segment gss_segments[] = {
+	{0x89000000, 0x00D00000}
+};
+
+static struct ramdump_segment smem_segments[] = {
+	{0x80000000, 0x00200000},
+};
+
+static int gss_ramdump(int enable, const struct subsys_desc *desc)
+{
+	int ret;
+	struct gss_data *drv = container_of(desc, struct gss_data, subsys_desc);
+
+	if (enable) {
+		ret = do_ramdump(drv->ramdump_dev, gss_segments,
+				ARRAY_SIZE(gss_segments));
+		if (ret < 0) {
+			pr_err("Unable to dump gss memory\n");
+			return ret;
+		}
+
+		ret = do_ramdump(drv->smem_ramdump_dev, smem_segments,
+			ARRAY_SIZE(smem_segments));
+		if (ret < 0) {
+			pr_err("Unable to dump smem memory (rc = %d).\n", ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static irqreturn_t gss_wdog_bite_irq(int irq, void *dev_id)
+{
+	struct gss_data *drv = dev_id;
+
+	pr_err("Watchdog bite received from GSS!\n");
+	restart_gss(drv);
+
+	return IRQ_HANDLED;
+}
+
+static int gss_open(struct inode *inode, struct file *filp)
+{
+	void *ret;
+	struct miscdevice *c = filp->private_data;
+	struct gss_data *drv = container_of(c, struct gss_data, misc_dev);
+
+	drv->pil_handle = ret = pil_get("gss");
+	if (!ret)
+		pr_debug("%s - pil_get returned NULL\n", __func__);
+
+	return 0;
+}
+
+static int gss_release(struct inode *inode, struct file *filp)
+{
+	struct miscdevice *c = filp->private_data;
+	struct gss_data *drv = container_of(c, struct gss_data, misc_dev);
+
+	pil_put(drv->pil_handle);
+	pr_debug("%s pil_put called on GSS\n", __func__);
+
+	return 0;
+}
+
+const struct file_operations gss_file_ops = {
+	.open = gss_open,
+	.release = gss_release,
+	.owner = THIS_MODULE,
+};
+
 static int __devinit pil_gss_probe(struct platform_device *pdev)
 {
 	struct gss_data *drv;
 	struct resource *res;
 	struct pil_desc *desc;
+	int ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -344,6 +508,10 @@
 	if (IS_ERR(drv->xo))
 		return PTR_ERR(drv->xo);
 
+	drv->irq = platform_get_irq(pdev, 0);
+	if (drv->irq < 0)
+		return drv->irq;
+
 	desc->name = "gss";
 	desc->dev = &pdev->dev;
 	desc->owner = THIS_MODULE;
@@ -363,13 +531,71 @@
 	if (IS_ERR(drv->pil)) {
 		return PTR_ERR(drv->pil);
 	}
+
+	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
+			smsm_state_cb, drv);
+	if (ret < 0)
+		dev_warn(&pdev->dev, "Unable to register SMSM callback\n");
+
+	drv->subsys_desc.name = "gss";
+	drv->subsys_desc.shutdown = gss_shutdown;
+	drv->subsys_desc.powerup = gss_powerup;
+	drv->subsys_desc.ramdump = gss_ramdump;
+	drv->subsys_desc.crash_shutdown = gss_crash_shutdown;
+
+	drv->subsys = subsys_register(&drv->subsys_desc);
+	if (IS_ERR(drv->subsys)) {
+		ret = PTR_ERR(drv->subsys);
+		goto err_subsys;
+	}
+
+	drv->misc_dev.minor = MISC_DYNAMIC_MINOR;
+	drv->misc_dev.name = "gss";
+	drv->misc_dev.fops = &gss_file_ops;
+	ret = misc_register(&drv->misc_dev);
+	if (ret)
+		goto err_misc;
+
+	drv->ramdump_dev = create_ramdump_device("gss");
+	if (!drv->ramdump_dev) {
+		ret = -ENOMEM;
+		goto err_ramdump;
+	}
+
+	drv->smem_ramdump_dev = create_ramdump_device("smem-gss");
+	if (!drv->smem_ramdump_dev) {
+		ret = -ENOMEM;
+		goto err_smem;
+	}
+
+	ret = devm_request_irq(&pdev->dev, drv->irq, gss_wdog_bite_irq,
+			IRQF_TRIGGER_RISING, "gss_a5_wdog", drv);
+	if (ret < 0)
+		goto err;
 	return 0;
+err:
+	destroy_ramdump_device(drv->smem_ramdump_dev);
+err_smem:
+	destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+	misc_deregister(&drv->misc_dev);
+err_misc:
+	subsys_unregister(drv->subsys);
+err_subsys:
+	msm_pil_unregister(drv->pil);
+	return ret;
 }
 
 static int __devexit pil_gss_remove(struct platform_device *pdev)
 {
 	struct gss_data *drv = platform_get_drvdata(pdev);
+
+	destroy_ramdump_device(drv->smem_ramdump_dev);
+	destroy_ramdump_device(drv->ramdump_dev);
+	misc_deregister(&drv->misc_dev);
+	subsys_unregister(drv->subsys);
 	msm_pil_unregister(drv->pil);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index 28b9dee..1a226de 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -19,9 +19,15 @@
 #include <linux/elf.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
 
 #include <mach/msm_iomap.h>
+#include <mach/subsystem_restart.h>
+#include <mach/scm.h>
+#include <mach/peripheral-loader.h>
 
+#include "ramdump.h"
 #include "peripheral-loader.h"
 #include "scm-pas.h"
 
@@ -60,11 +66,34 @@
 #define Q6_STRAP_TCM_BASE	(0x28C << 15)
 #define Q6_STRAP_TCM_CONFIG	0x28B
 
+#define SCM_Q6_NMI_CMD		0x1
+
+/**
+ * struct q6v3_data - LPASS driver data
+ * @base: register base
+ * @wk_base: wakeup register base
+ * @wd_base: watchdog register base
+ * @start_addr: address that processor starts running at
+ * @irq: watchdog irq
+ * @pil: peripheral handle
+ * @subsys: subsystem restart handle
+ * @subsys_desc: subsystem restart descriptor
+ * @fatal_wrk: fatal error workqueue
+ * @pll: pll clock handle
+ * @ramdump_dev: ramdump device
+ */
 struct q6v3_data {
 	void __iomem *base;
+	void __iomem *wk_base;
+	void __iomem *wd_base;
 	unsigned long start_addr;
+	int irq;
 	struct pil_device *pil;
+	struct subsys_device *subsys;
+	struct subsys_desc subsys_desc;
+	struct work_struct fatal_wrk;
 	struct clk *pll;
+	struct ramdump_device *ramdump_dev;
 };
 
 static int pil_q6v3_init_image(struct pil_desc *pil, const u8 *metadata,
@@ -198,11 +227,96 @@
 	.proxy_unvote = pil_q6v3_remove_proxy_votes,
 };
 
+static void q6_fatal_fn(struct work_struct *work)
+{
+	struct q6v3_data *drv = container_of(work, struct q6v3_data, fatal_wrk);
+
+	pr_err("Watchdog bite received from Q6!\n");
+	subsystem_restart_dev(drv->subsys);
+	enable_irq(drv->irq);
+}
+
+static void send_q6_nmi(struct q6v3_data *drv)
+{
+	/* Send NMI to QDSP6 via an SCM call. */
+	scm_call_atomic1(SCM_SVC_UTIL, SCM_Q6_NMI_CMD, 0x1);
+
+	/* Wakeup the Q6 */
+	writel_relaxed(0x2000, drv->wk_base + 0x1c);
+	/* Q6 requires atleast 100ms to dump caches etc.*/
+	mdelay(100);
+	pr_info("Q6 NMI was sent.\n");
+}
+
+static int lpass_q6_shutdown(const struct subsys_desc *subsys)
+{
+	struct q6v3_data *drv;
+
+	drv = container_of(subsys, struct q6v3_data, subsys_desc);
+	send_q6_nmi(drv);
+	writel_relaxed(0x0, drv->wd_base + 0x24);
+	mb();
+
+	pil_force_shutdown("q6");
+	disable_irq_nosync(drv->irq);
+
+	return 0;
+}
+
+static int lpass_q6_powerup(const struct subsys_desc *subsys)
+{
+	struct q6v3_data *drv;
+	int ret;
+
+	drv = container_of(subsys, struct q6v3_data, subsys_desc);
+	ret = pil_force_boot("q6");
+	enable_irq(drv->irq);
+	return ret;
+}
+
+/* FIXME: Get address, size from PIL */
+static struct ramdump_segment q6_segments[] = {
+	{ 0x46700000, 0x47f00000 - 0x46700000 },
+	{ 0x28400000, 0x12800 }
+};
+
+static int lpass_q6_ramdump(int enable, const struct subsys_desc *subsys)
+{
+	struct q6v3_data *drv;
+
+	drv = container_of(subsys, struct q6v3_data, subsys_desc);
+	if (enable)
+		return do_ramdump(drv->ramdump_dev, q6_segments,
+				ARRAY_SIZE(q6_segments));
+	else
+		return 0;
+}
+
+static void lpass_q6_crash_shutdown(const struct subsys_desc *subsys)
+{
+	struct q6v3_data *drv;
+
+	drv = container_of(subsys, struct q6v3_data, subsys_desc);
+	send_q6_nmi(drv);
+}
+
+static irqreturn_t lpass_wdog_bite_irq(int irq, void *dev_id)
+{
+	int ret;
+	struct q6v3_data *drv = dev_id;
+
+	ret = schedule_work(&drv->fatal_wrk);
+	disable_irq_nosync(drv->irq);
+
+	return IRQ_HANDLED;
+}
+
 static int __devinit pil_q6v3_driver_probe(struct platform_device *pdev)
 {
 	struct q6v3_data *drv;
 	struct resource *res;
 	struct pil_desc *desc;
+	int ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -217,14 +331,34 @@
 	if (!drv->base)
 		return -ENOMEM;
 
-	desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
-	if (!drv)
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -EINVAL;
+
+	drv->wk_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!drv->wk_base)
 		return -ENOMEM;
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (!res)
+		return -EINVAL;
+
+	drv->wd_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!drv->wd_base)
+		return -ENOMEM;
+
+	drv->irq = platform_get_irq(pdev, 0);
+	if (drv->irq < 0)
+		return drv->irq;
+
 	drv->pll = devm_clk_get(&pdev->dev, "pll4");
 	if (IS_ERR(drv->pll))
 		return PTR_ERR(drv->pll);
 
+	desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+	if (!drv)
+		return -ENOMEM;
+
 	desc->name = "q6";
 	desc->dev = &pdev->dev;
 	desc->owner = THIS_MODULE;
@@ -239,15 +373,51 @@
 	}
 
 	drv->pil = msm_pil_register(desc);
-	if (IS_ERR(drv->pil)) {
+	if (IS_ERR(drv->pil))
 		return PTR_ERR(drv->pil);
+
+	drv->subsys_desc.name = "lpass";
+	drv->subsys_desc.shutdown = lpass_q6_shutdown;
+	drv->subsys_desc.powerup = lpass_q6_powerup;
+	drv->subsys_desc.ramdump = lpass_q6_ramdump;
+	drv->subsys_desc.crash_shutdown = lpass_q6_crash_shutdown;
+
+	INIT_WORK(&drv->fatal_wrk, q6_fatal_fn);
+
+	drv->ramdump_dev = create_ramdump_device("lpass");
+	if (!drv->ramdump_dev) {
+		ret = -ENOMEM;
+		goto err_ramdump;
 	}
+
+	drv->subsys = subsys_register(&drv->subsys_desc);
+	if (IS_ERR(drv->subsys)) {
+		ret = PTR_ERR(drv->subsys);
+		goto err_subsys;
+	}
+
+	ret = devm_request_irq(&pdev->dev, drv->irq, lpass_wdog_bite_irq,
+			       IRQF_TRIGGER_RISING, "lpass_wdog", drv);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to request wdog irq.\n");
+		goto err_irq;
+	}
+
 	return 0;
+err_irq:
+	subsys_unregister(drv->subsys);
+err_subsys:
+	destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+	msm_pil_unregister(drv->pil);
+	return ret;
 }
 
 static int __devexit pil_q6v3_driver_exit(struct platform_device *pdev)
 {
 	struct q6v3_data *drv = platform_get_drvdata(pdev);
+	subsys_unregister(drv->subsys);
+	destroy_ramdump_device(drv->ramdump_dev);
 	msm_pil_unregister(drv->pil);
 	return 0;
 }
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 3040a31..dbb4408 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -20,11 +20,17 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/wcnss_wlan.h>
 
 #include <mach/msm_iomap.h>
+#include <mach/subsystem_restart.h>
+#include <mach/peripheral-loader.h>
 
 #include "peripheral-loader.h"
 #include "scm-pas.h"
+#include "ramdump.h"
+#include "smd_private.h"
 
 #define RIVA_PMU_A2XB_CFG		0xB8
 #define RIVA_PMU_A2XB_CFG_EN		BIT(0)
@@ -82,6 +88,13 @@
 	struct clk *xo;
 	struct regulator *pll_supply;
 	struct pil_device *pil;
+	int irq;
+	int crash;
+	int rst_in_progress;
+	struct subsys_device *subsys;
+	struct subsys_desc subsys_desc;
+	struct delayed_work cancel_work;
+	struct ramdump_device *ramdump_dev;
 };
 
 static bool cxo_is_needed(struct riva_data *drv)
@@ -272,6 +285,160 @@
 	.proxy_unvote = pil_riva_remove_proxy_vote,
 };
 
+static int enable_riva_ssr;
+
+static int enable_riva_ssr_set(const char *val, struct kernel_param *kp)
+{
+	int ret;
+
+	ret = param_set_int(val, kp);
+	if (ret)
+		return ret;
+
+	if (enable_riva_ssr)
+		pr_info("Subsystem restart activated for riva.\n");
+
+	return 0;
+}
+module_param_call(enable_riva_ssr, enable_riva_ssr_set, param_get_int,
+		 &enable_riva_ssr, S_IRUGO | S_IWUSR);
+
+static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
+			       uint32_t new_state)
+{
+	struct riva_data *drv = data;
+	char *smem_reset_reason;
+	char buffer[81];
+	unsigned smem_reset_size;
+	unsigned size;
+
+	drv->crash = true;
+	if (!(new_state & SMSM_RESET))
+		return;
+
+	if (drv->rst_in_progress) {
+		pr_err("riva: Ignoring smsm reset req, restart in progress\n");
+		return;
+	}
+
+	pr_err("riva: smsm state changed to smsm reset\n");
+
+	smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
+		&smem_reset_size);
+
+	if (!smem_reset_reason || !smem_reset_size) {
+		pr_err("wcnss subsystem failure reason:\n"
+		       "(unknown, smem_get_entry failed)");
+	} else if (!smem_reset_reason[0]) {
+		pr_err("wcnss subsystem failure reason:\n"
+		       "(unknown, init string found)");
+	} else {
+		size = smem_reset_size < sizeof(buffer) ? smem_reset_size :
+				(sizeof(buffer) - 1);
+		memcpy(buffer, smem_reset_reason, size);
+		buffer[size] = '\0';
+		pr_err("wcnss subsystem failure reason: %s\n", buffer);
+		memset(smem_reset_reason, 0, smem_reset_size);
+		wmb();
+	}
+
+	drv->rst_in_progress = 1;
+	subsystem_restart_dev(drv->subsys);
+}
+
+static irqreturn_t riva_wdog_bite_irq_hdlr(int irq, void *dev_id)
+{
+	struct riva_data *drv = dev_id;
+
+	drv->crash = true;
+	if (drv->rst_in_progress) {
+		pr_err("Ignoring riva bite irq, restart in progress\n");
+		return IRQ_HANDLED;
+	}
+	if (!enable_riva_ssr)
+		panic("Watchdog bite received from Riva");
+
+	drv->rst_in_progress = 1;
+	subsystem_restart_dev(drv->subsys);
+
+	return IRQ_HANDLED;
+}
+
+static void riva_post_bootup(struct work_struct *work)
+{
+	struct platform_device *pdev = wcnss_get_platform_device();
+	struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
+
+	wcnss_wlan_power(&pdev->dev, pwlanconfig, WCNSS_WLAN_SWITCH_OFF);
+}
+
+static int riva_shutdown(const struct subsys_desc *desc)
+{
+	struct riva_data *drv;
+
+	drv = container_of(desc, struct riva_data, subsys_desc);
+	pil_force_shutdown("wcnss");
+	flush_delayed_work(&drv->cancel_work);
+	wcnss_flush_delayed_boot_votes();
+	disable_irq_nosync(drv->irq);
+
+	return 0;
+}
+
+static int riva_powerup(const struct subsys_desc *desc)
+{
+	struct riva_data *drv;
+	struct platform_device *pdev = wcnss_get_platform_device();
+	struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
+	int ret = 0;
+
+	drv = container_of(desc, struct riva_data, subsys_desc);
+	if (pdev && pwlanconfig) {
+		ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
+					WCNSS_WLAN_SWITCH_ON);
+		if (!ret)
+			pil_force_boot("wcnss");
+	}
+	drv->rst_in_progress = 0;
+	enable_irq(drv->irq);
+	schedule_delayed_work(&drv->cancel_work, msecs_to_jiffies(5000));
+
+	return ret;
+}
+
+/*
+ * 7MB RAM segments for Riva SS;
+ * Riva 1.1 0x8f000000 - 0x8f700000
+ * Riva 1.0 0x8f200000 - 0x8f700000
+ */
+static struct ramdump_segment riva_segments[] = {
+	{0x8f000000, 0x8f700000 - 0x8f000000}
+};
+
+static int riva_ramdump(int enable, const struct subsys_desc *desc)
+{
+	struct riva_data *drv;
+
+	drv = container_of(desc, struct riva_data, subsys_desc);
+
+	if (enable)
+		return do_ramdump(drv->ramdump_dev, riva_segments,
+				ARRAY_SIZE(riva_segments));
+	else
+		return 0;
+}
+
+/* Riva crash handler */
+static void riva_crash_shutdown(const struct subsys_desc *desc)
+{
+	struct riva_data *drv;
+
+	drv = container_of(desc, struct riva_data, subsys_desc);
+	pr_err("riva crash shutdown %d\n", drv->crash);
+	if (drv->crash != true)
+		smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
+}
+
 static int __devinit pil_riva_probe(struct platform_device *pdev)
 {
 	struct riva_data *drv;
@@ -317,6 +484,10 @@
 		}
 	}
 
+	drv->irq = platform_get_irq(pdev, 0);
+	if (drv->irq < 0)
+		return drv->irq;
+
 	desc->name = "wcnss";
 	desc->dev = &pdev->dev;
 	desc->owner = THIS_MODULE;
@@ -337,13 +508,60 @@
 	drv->pil = msm_pil_register(desc);
 	if (IS_ERR(drv->pil))
 		return PTR_ERR(drv->pil);
+
+	ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
+					smsm_state_cb_hdlr, drv);
+	if (ret < 0)
+		goto err_smsm;
+
+	drv->subsys_desc.name = "wcnss";
+	drv->subsys_desc.shutdown = riva_shutdown;
+	drv->subsys_desc.powerup = riva_powerup;
+	drv->subsys_desc.ramdump = riva_ramdump;
+	drv->subsys_desc.crash_shutdown = riva_crash_shutdown;
+
+	INIT_DELAYED_WORK(&drv->cancel_work, riva_post_bootup);
+
+	drv->ramdump_dev = create_ramdump_device("riva");
+	if (!drv->ramdump_dev) {
+		ret = -ENOMEM;
+		goto err_ramdump;
+	}
+
+	drv->subsys = subsys_register(&drv->subsys_desc);
+	if (IS_ERR(drv->subsys)) {
+		ret = PTR_ERR(drv->subsys);
+		goto err_subsys;
+	}
+
+	ret = devm_request_irq(&pdev->dev, drv->irq, riva_wdog_bite_irq_hdlr,
+			IRQF_TRIGGER_HIGH, "riva_wdog", drv);
+	if (ret < 0)
+		goto err;
+
 	return 0;
+err:
+	subsys_unregister(drv->subsys);
+err_subsys:
+	destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+	smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
+					smsm_state_cb_hdlr, drv);
+err_smsm:
+	msm_pil_unregister(drv->pil);
+	return ret;
 }
 
 static int __devexit pil_riva_remove(struct platform_device *pdev)
 {
 	struct riva_data *drv = platform_get_drvdata(pdev);
+
+	subsys_unregister(drv->subsys);
+	destroy_ramdump_device(drv->ramdump_dev);
+	smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
+					smsm_state_cb_hdlr, drv);
 	msm_pil_unregister(drv->pil);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/rpm-regulator-8960.c b/arch/arm/mach-msm/rpm-regulator-8960.c
index 8fe3571..c5c01c2 100644
--- a/arch/arm/mach-msm/rpm-regulator-8960.c
+++ b/arch/arm/mach-msm/rpm-regulator-8960.c
@@ -325,3 +325,32 @@
 {
 	return &config;
 }
+
+struct vreg_config *get_config_8960_pm8917(void)
+{
+	int i;
+
+	/*
+	 * PM8917 regulators L24, L25, L26, L27, and L28 require CXO to be ON
+	 * while they are enabled.  These same regulators on PM8921 do not
+	 * require CXO to be ON.  Therefore, set the require_cxo flag for these
+	 * regulators only when using PM8917.
+	 *
+	 * Do not apply the workaround to L24 (VDD_MX) because it is always on
+	 * and using the TCXO workaround with it would result in additional
+	 * latency during every Krait upscaling event.
+	 */
+	for (i = 0; i < ARRAY_SIZE(vregs); i++) {
+		switch (vregs[i].id) {
+		case RPM_VREG_ID_PM8921_L25:
+		case RPM_VREG_ID_PM8921_L26:
+		case RPM_VREG_ID_PM8921_L27:
+		case RPM_VREG_ID_PM8921_L28:
+			vregs[i].requires_cxo = true;
+		default:
+			break;
+		}
+	}
+
+	return &config;
+}
diff --git a/arch/arm/mach-msm/rpm-regulator-private.h b/arch/arm/mach-msm/rpm-regulator-private.h
index d55bd73..703335f 100644
--- a/arch/arm/mach-msm/rpm-regulator-private.h
+++ b/arch/arm/mach-msm/rpm-regulator-private.h
@@ -158,11 +158,16 @@
 #if defined(CONFIG_MSM_RPM_REGULATOR) && \
 	(defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064))
 struct vreg_config *get_config_8960(void);
+struct vreg_config *get_config_8960_pm8917(void);
 #else
 static inline struct vreg_config *get_config_8960(void)
 {
 	return NULL;
 }
+static inline struct vreg_config *get_config_8960_pm8917(void)
+{
+	return NULL;
+}
 #endif
 
 #if defined(CONFIG_MSM_RPM_REGULATOR) && defined(CONFIG_ARCH_MSM9615)
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index a8af9e7..9c621c4 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -1286,7 +1286,7 @@
 		}
 	}
 
-	of_property_read_u32(node, "qcom,system_load", &reg->system_load);
+	of_property_read_u32(node, "qcom,system-load", &reg->system_load);
 
 	rpm_vreg_lock(rpm_vreg);
 	list_add(&reg->list, &rpm_vreg->reg_list);
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index 424a4fe..01543a2 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -63,6 +63,7 @@
 	[RPM_VREG_VERSION_9615] = get_config_9615,
 	[RPM_VREG_VERSION_8930] = get_config_8930,
 	[RPM_VREG_VERSION_8930_PM8917] = get_config_8930_pm8917,
+	[RPM_VREG_VERSION_8960_PM8917] = get_config_8960_pm8917,
 };
 
 static struct rpm_regulator_consumer_mapping *consumer_map;
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index dd24e20..8da1d75 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -25,8 +25,29 @@
 	PAS_VIDC,
 };
 
+#ifdef CONFIG_MSM_PIL
 extern int pas_init_image(enum pas_id id, const u8 *metadata, size_t size);
 extern int pas_auth_and_reset(enum pas_id id);
 extern int pas_shutdown(enum pas_id id);
 extern int pas_supported(enum pas_id id);
+#else
+static inline int pas_init_image(enum pas_id id, const u8 *metadata,
+		size_t size)
+{
+	return 0;
+}
+static inline int pas_auth_and_reset(enum pas_id id)
+{
+	return 0;
+}
+static inline int pas_shutdown(enum pas_id id)
+{
+	return 0;
+}
+static inline int pas_supported(enum pas_id id)
+{
+	return 0;
+}
+#endif
+
 #endif
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
deleted file mode 100644
index 5516e30..0000000
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. 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/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/wcnss_wlan.h>
-#include <linux/err.h>
-#include <asm/mach-types.h>
-#include <mach/irqs.h>
-#include <mach/scm.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-#include <mach/peripheral-loader.h>
-#include "smd_private.h"
-#include "ramdump.h"
-
-#define MODULE_NAME			"wcnss_8960"
-#define MAX_BUF_SIZE			0x51
-
-
-
-static struct delayed_work cancel_vote_work;
-static void *riva_ramdump_dev;
-static int riva_crash;
-static int ss_restart_inprogress;
-static int enable_riva_ssr;
-static struct subsys_device *riva_8960_dev;
-
-static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
-					uint32_t new_state)
-{
-	char *smem_reset_reason;
-	char buffer[MAX_BUF_SIZE];
-	unsigned smem_reset_size;
-	unsigned size;
-
-	riva_crash = true;
-
-	pr_err("%s: smsm state changed\n", MODULE_NAME);
-
-	if (!(new_state & SMSM_RESET))
-		return;
-
-	if (ss_restart_inprogress) {
-		pr_err("%s: Ignoring smsm reset req, restart in progress\n",
-						MODULE_NAME);
-		return;
-	}
-
-	if (!enable_riva_ssr)
-		panic(MODULE_NAME ": SMSM reset request received from Riva");
-
-	smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
-			&smem_reset_size);
-
-	if (!smem_reset_reason || !smem_reset_size) {
-		pr_err("%s: wcnss subsystem failure reason: %s\n",
-				__func__, "(unknown, smem_get_entry failed)");
-	} else if (!smem_reset_reason[0]) {
-		pr_err("%s: wcnss subsystem failure reason: %s\n",
-				__func__, "(unknown, init string found)");
-	} else {
-		size = smem_reset_size < MAX_BUF_SIZE ? smem_reset_size :
-			(MAX_BUF_SIZE - 1);
-		memcpy(buffer, smem_reset_reason, size);
-		buffer[size] = '\0';
-		pr_err("%s: wcnss subsystem failure reason: %s\n",
-				__func__, buffer);
-		memset(smem_reset_reason, 0, smem_reset_size);
-		wmb();
-	}
-
-	ss_restart_inprogress = true;
-	subsystem_restart_dev(riva_8960_dev);
-}
-
-static irqreturn_t riva_wdog_bite_irq_hdlr(int irq, void *dev_id)
-{
-	riva_crash = true;
-
-	if (ss_restart_inprogress) {
-		pr_err("%s: Ignoring riva bite irq, restart in progress\n",
-						MODULE_NAME);
-		return IRQ_HANDLED;
-	}
-
-	if (!enable_riva_ssr)
-		panic(MODULE_NAME ": Watchdog bite received from Riva");
-
-	ss_restart_inprogress = true;
-	subsystem_restart_dev(riva_8960_dev);
-
-	return IRQ_HANDLED;
-}
-
-/* SMSM reset Riva */
-static void smsm_riva_reset(void)
-{
-	/* per SS reset request bit is not available now,
-	 * all SS host modules are setting this bit
-	 * This is still under discussion*/
-	smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
-}
-
-static void riva_post_bootup(struct work_struct *work)
-{
-	struct platform_device *pdev = wcnss_get_platform_device();
-	struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
-
-	pr_debug(MODULE_NAME ": Cancel APPS vote for Iris & Riva\n");
-
-	wcnss_wlan_power(&pdev->dev, pwlanconfig,
-		WCNSS_WLAN_SWITCH_OFF);
-}
-
-/* Subsystem handlers */
-static int riva_shutdown(const struct subsys_desc *subsys)
-{
-	pil_force_shutdown("wcnss");
-	flush_delayed_work(&cancel_vote_work);
-	wcnss_flush_delayed_boot_votes();
-	disable_irq_nosync(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
-
-	return 0;
-}
-
-static int riva_powerup(const struct subsys_desc *subsys)
-{
-	struct platform_device *pdev = wcnss_get_platform_device();
-	struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
-	int    ret = -1;
-
-	if (pdev && pwlanconfig)
-		ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
-					WCNSS_WLAN_SWITCH_ON);
-	/* delay PIL operation, this SSR may be happening soon after kernel
-	 * resumes because of a SMSM RESET by Riva when APPS was suspended.
-	 * PIL fails to locate the images without this delay */
-	if (!ret) {
-		msleep(1000);
-		pil_force_boot("wcnss");
-	}
-	ss_restart_inprogress = false;
-	enable_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
-	schedule_delayed_work(&cancel_vote_work, msecs_to_jiffies(5000));
-
-	return ret;
-}
-
-/* 5MB RAM segments for Riva SS */
-static struct ramdump_segment riva_segments[] = {{0x8f200000,
-						0x8f700000 - 0x8f200000} };
-
-static int riva_ramdump(int enable, const struct subsys_desc *subsys)
-{
-	pr_debug("%s: enable[%d]\n", MODULE_NAME, enable);
-	if (enable)
-		return do_ramdump(riva_ramdump_dev,
-				riva_segments,
-				ARRAY_SIZE(riva_segments));
-	else
-		return 0;
-}
-
-/* Riva crash handler */
-static void riva_crash_shutdown(const struct subsys_desc *subsys)
-{
-	pr_err("%s: crash shutdown : %d\n", MODULE_NAME, riva_crash);
-	if (riva_crash != true)
-		smsm_riva_reset();
-}
-
-static struct subsys_desc riva_8960 = {
-	.name = "wcnss",
-	.shutdown = riva_shutdown,
-	.powerup = riva_powerup,
-	.ramdump = riva_ramdump,
-	.crash_shutdown = riva_crash_shutdown
-};
-
-static int enable_riva_ssr_set(const char *val, struct kernel_param *kp)
-{
-	int ret;
-
-	ret = param_set_int(val, kp);
-	if (ret)
-		return ret;
-
-	if (enable_riva_ssr)
-		pr_info(MODULE_NAME ": Subsystem restart activated for riva.\n");
-
-	return 0;
-}
-
-module_param_call(enable_riva_ssr, enable_riva_ssr_set, param_get_int,
-			&enable_riva_ssr, S_IRUGO | S_IWUSR);
-
-static int __init riva_restart_init(void)
-{
-	riva_8960_dev = subsys_register(&riva_8960);
-	if (IS_ERR(riva_8960_dev))
-		return PTR_ERR(riva_8960_dev);
-	return 0;
-}
-
-static int __init riva_ssr_module_init(void)
-{
-	int ret;
-
-	if (machine_is_mpq8064_hrd()) {
-		pr_err("Riva not supported on this target\n");
-		return 0;
-	}
-
-	ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
-					smsm_state_cb_hdlr, 0);
-	if (ret < 0) {
-		pr_err("%s: Unable to register smsm callback for Riva Reset! %d\n",
-				MODULE_NAME, ret);
-		goto out;
-	}
-	ret = request_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
-			riva_wdog_bite_irq_hdlr, IRQF_TRIGGER_HIGH,
-				"riva_wdog", NULL);
-
-	if (ret < 0) {
-		pr_err("%s: Unable to register for Riva bite interrupt (%d)\n",
-				MODULE_NAME, ret);
-		goto out;
-	}
-	ret = riva_restart_init();
-	if (ret < 0) {
-		pr_err("%s: Unable to register with ssr. (%d)\n",
-				MODULE_NAME, ret);
-		goto out;
-	}
-	riva_ramdump_dev = create_ramdump_device("riva");
-	if (!riva_ramdump_dev) {
-		pr_err("%s: Unable to create ramdump device.\n",
-				MODULE_NAME);
-		ret = -ENOMEM;
-		goto out;
-	}
-	INIT_DELAYED_WORK(&cancel_vote_work, riva_post_bootup);
-
-	pr_info("%s: module initialized\n", MODULE_NAME);
-out:
-	return ret;
-}
-
-static void __exit riva_ssr_module_exit(void)
-{
-	if (machine_is_mpq8064_hrd())
-		return;
-	subsys_unregister(riva_8960_dev);
-	free_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ, NULL);
-}
-
-module_init(riva_ssr_module_init);
-module_exit(riva_ssr_module_exit);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/bluetooth/hci_ibs.c b/drivers/bluetooth/hci_ibs.c
index 6253605..acff5a5 100644
--- a/drivers/bluetooth/hci_ibs.c
+++ b/drivers/bluetooth/hci_ibs.c
@@ -254,13 +254,14 @@
 	struct ibs_struct *ibs = container_of(work, struct ibs_struct,
 					ws_awake_device);
 	struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+	unsigned long flags;
 
 	BT_DBG(" %p ", hu);
 
 	/* Vote for serial clock */
 	ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
 
-	spin_lock(&ibs->hci_ibs_lock);
+	spin_lock_irqsave(&ibs->hci_ibs_lock, flags);
 
 	/* send wake indication to device */
 	if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0)
@@ -271,7 +272,8 @@
 	/* start retransmit timer */
 	mod_timer(&ibs->wake_retrans_timer, jiffies + wake_retrans);
 
-	spin_unlock(&ibs->hci_ibs_lock);
+	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+
 }
 
 static void ibs_wq_awake_rx(struct work_struct *work)
@@ -279,12 +281,14 @@
 	struct ibs_struct *ibs = container_of(work, struct ibs_struct,
 					ws_awake_rx);
 	struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+	unsigned long flags;
 
 	BT_DBG(" %p ", hu);
 
 	ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
 
-	spin_lock(&ibs->hci_ibs_lock);
+	spin_lock_irqsave(&ibs->hci_ibs_lock, flags);
+
 	ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;
 	/* Always acknowledge device wake up,
 	 * sending IBS message doesn't count as TX ON
@@ -294,7 +298,8 @@
 
 	ibs->ibs_sent_wacks++; /* debug */
 
-	spin_unlock(&ibs->hci_ibs_lock);
+	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+
 	/* actually send the packets */
 	hci_uart_tx_wakeup(hu);
 
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 09da40c..5c6cdc6 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1422,9 +1422,9 @@
 		INIT_WORK(&(driver->diag_clean_wcnss_reg_work),
 						 diag_clean_wcnss_reg_fn);
 		diag_debugfs_init();
+		diag_masks_init();
 		diagfwd_init();
 		diagfwd_cntl_init();
-		diag_masks_init();
 		driver->dci_state = diag_dci_init();
 		diag_sdio_fn(INIT);
 		diag_bridge_fn(INIT);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index e0d40be..129ca7e 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2163,6 +2163,9 @@
 	if (!adreno_dev->fast_hang_detect)
 		return 0;
 
+	if (device->ftbl->isidle(device))
+		return 0;
+
 	for (i = 0; i < hang_detect_regs_count; i++) {
 
 		if (hang_detect_regs[i] == 0)
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 664d519..5ba844a 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1752,6 +1752,8 @@
 	if (result)
 		goto error;
 
+	entry->memdesc.priv |= param->flags & KGSL_MEMTYPE_MASK;
+
 	result = kgsl_mmu_map(private->pagetable,
 			      &entry->memdesc,
 			      GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 0e1e100..54ba5ad 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -729,7 +729,8 @@
 		return 0;
 
 	gpuaddr = memdesc->gpuaddr;
-	memdesc->priv |= KGSL_MEMFLAGS_GLOBAL;
+	memdesc->priv |= KGSL_MEMFLAGS_GLOBAL
+			| (KGSL_MEMTYPE_KERNEL << KGSL_MEMTYPE_SHIFT);
 
 	result = kgsl_mmu_map(pagetable, memdesc, protflags);
 	if (result)
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index c2ce5c7..bdc5686 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -540,7 +540,6 @@
 
 	memdesc->size = size;
 	memdesc->pagetable = pagetable;
-	memdesc->priv = KGSL_MEMFLAGS_CACHED;
 	memdesc->ops = &kgsl_page_alloc_ops;
 
 	memdesc->sg = kgsl_sg_alloc(sglen);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index de89ac1..5a6c4c2 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -27,8 +27,6 @@
 #define KGSL_CACHE_OP_FLUSH     0x02
 #define KGSL_CACHE_OP_CLEAN     0x03
 
-/** Set if the memdesc describes cached memory */
-#define KGSL_MEMFLAGS_CACHED    0x00000001
 /** Set if the memdesc is mapped into all pagetables */
 #define KGSL_MEMFLAGS_GLOBAL    0x00000002
 
@@ -136,6 +134,7 @@
 {
 	if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE)
 		return kgsl_sharedmem_ebimem(memdesc, pagetable, size);
+	memdesc->priv |= (KGSL_MEMTYPE_KERNEL << KGSL_MEMTYPE_SHIFT);
 	return kgsl_sharedmem_page_alloc(memdesc, pagetable, size);
 }
 
@@ -144,10 +143,17 @@
 		struct kgsl_pagetable *pagetable,
 		size_t size, unsigned int flags)
 {
+	int ret;
+	unsigned int mask = (KGSL_MEMTYPE_MASK | KGSL_MEMFLAGS_GPUREADONLY);
 	if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE)
-		return kgsl_sharedmem_ebimem_user(memdesc, pagetable, size,
+		ret = kgsl_sharedmem_ebimem_user(memdesc, pagetable, size,
 						  flags);
-	return kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size, flags);
+	else
+		ret = kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size,
+							flags);
+	if (ret == 0)
+		memdesc->priv |= flags & mask;
+	return ret;
 }
 
 static inline int
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 2c95ef5..77922e2 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -711,8 +711,12 @@
 
 	int rc = -EINVAL;
 	void __user *argp = (void __user *)arg;
-	struct v4l2_subdev *sd = pmctl->vfe_sdev;
-
+	struct v4l2_subdev *sd;
+	if (!pmctl->vfe_sdev) {
+		pr_err("%s vfe subdev is NULL\n", __func__);
+		return -ENXIO;
+	}
+	sd = pmctl->vfe_sdev;
 	D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
 	switch (cmd) {
 	case MSM_CAM_IOCTL_CONFIG_VFE:
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index aa39aad..a017cf2 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -304,7 +304,7 @@
 	}
 	if (irq & 0x01000000) {
 		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
-			VCAP_VC_LINE_ERR_EVENT;
+			VCAP_VP_REG_W_ERR_EVENT;
 		v4l2_event_queue(dev->vfd, &v4l2_evt);
 	}
 	if (irq & 0x00020000) {
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index b7d4c32..180a18a 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -306,10 +306,16 @@
 	uint32 is_fg;		/* control alpha & color key */
 	uint32 srcp0_addr;	/* interleave, luma */
 	uint32 srcp0_ystride;
+	struct file *srcp0_file;
+	int put0_need;
 	uint32 srcp1_addr;	/* pseudoplanar, chroma plane */
 	uint32 srcp1_ystride;
+	struct file *srcp1_file;
+	int put1_need;
 	uint32 srcp2_addr;	/* planar color 2*/
 	uint32 srcp2_ystride;
+	struct file *srcp2_file;
+	int put2_need;
 	uint32 srcp3_addr;	/* alpha/color 3 */
 	uint32 srcp3_ystride;
 	uint32 fetch_plane;
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 8f308c3..c7e811f 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -191,6 +191,19 @@
 	if (pipe == NULL)
 		return;
 
+	if (pipe->flags & MDP_MEMORY_ID_TYPE_FB) {
+		if (pipe->put0_need)
+			fput_light(pipe->srcp0_file, pipe->put0_need);
+		if (pipe->put1_need)
+			fput_light(pipe->srcp1_file, pipe->put1_need);
+		if (pipe->put2_need)
+			fput_light(pipe->srcp2_file, pipe->put2_need);
+
+		pr_debug("%s: ndx=%d flags=%x put=%d\n", __func__,
+			pipe->pipe_ndx, pipe->flags, pipe->put0_need);
+		return;
+	}
+
 	mutex_lock(&iommu_mutex);
 	mixer = pipe->mixer_num;
 	iom = &pipe->iommu;
@@ -2955,14 +2968,13 @@
 		if (file == NULL)
 			return -EINVAL;
 
+		pipe->flags |= MDP_MEMORY_ID_TYPE_FB;
 		if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
 			fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
 			if (get_fb_phys_info(start, len, fb_num,
 				DISPLAY_SUBSYSTEM_ID)) {
 				ret = -1;
 			} else {
-				pr_warn("%s: mdp4_overlay play with FB memory\n",
-							 __func__);
 				*srcp_file = file;
 				*p_need = put_needed;
 			}
@@ -3320,11 +3332,8 @@
 	struct mdp4_overlay_pipe *pipe;
 	ulong start, addr;
 	ulong len = 0;
-	struct file *srcp0_file = NULL;
-	struct file *srcp1_file = NULL, *srcp2_file = NULL;
 	struct ion_handle *srcp0_ihdl = NULL;
 	struct ion_handle *srcp1_ihdl = NULL, *srcp2_ihdl = NULL;
-	int ps0_need, p_need;
 	uint32_t overlay_version = 0;
 	int ret = 0;
 
@@ -3349,8 +3358,8 @@
 	mutex_lock(&mfd->dma->ov_mutex);
 
 	img = &req->data;
-	get_img(img, info, pipe, 0, &start, &len, &srcp0_file,
-		&ps0_need, &srcp0_ihdl);
+	get_img(img, info, pipe, 0, &start, &len, &pipe->srcp0_file,
+		&pipe->put0_need, &srcp0_ihdl);
 	if (len == 0) {
 		pr_err("%s: pmem Error\n", __func__);
 		ret = -1;
@@ -3372,8 +3381,9 @@
 	if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
 		if (overlay_version > 0) {
 			img = &req->plane1_data;
-			get_img(img, info, pipe, 1, &start, &len, &srcp1_file,
-				&p_need, &srcp1_ihdl);
+			get_img(img, info, pipe, 1, &start, &len,
+				&pipe->srcp1_file, &pipe->put1_need,
+				&srcp1_ihdl);
 			if (len == 0) {
 				pr_err("%s: Error to get plane1\n", __func__);
 				ret = -EINVAL;
@@ -3404,8 +3414,9 @@
 	} else if (pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
 		if (overlay_version > 0) {
 			img = &req->plane1_data;
-			get_img(img, info, pipe, 1, &start, &len, &srcp1_file,
-				&p_need, &srcp1_ihdl);
+			get_img(img, info, pipe, 1, &start, &len,
+				&pipe->srcp1_file, &pipe->put1_need,
+				&srcp1_ihdl);
 			if (len == 0) {
 				pr_err("%s: Error to get plane1\n", __func__);
 				ret = -EINVAL;
@@ -3414,8 +3425,9 @@
 			pipe->srcp1_addr = start + img->offset;
 
 			img = &req->plane2_data;
-			get_img(img, info, pipe, 2, &start, &len, &srcp2_file,
-				&p_need, &srcp2_ihdl);
+			get_img(img, info, pipe, 2, &start, &len,
+				&pipe->srcp2_file, &pipe->put2_need,
+				&srcp2_ihdl);
 			if (len == 0) {
 				pr_err("%s: Error to get plane2\n", __func__);
 				ret = -EINVAL;
@@ -3512,17 +3524,6 @@
 end:
 	mutex_unlock(&mfd->dma->ov_mutex);
 
-#ifdef CONFIG_ANDROID_PMEM
-	if (srcp0_file)
-		put_pmem_file(srcp0_file);
-	if (srcp1_file)
-		put_pmem_file(srcp1_file);
-	if (srcp2_file)
-		put_pmem_file(srcp2_file);
-#endif
-	/* only source may use frame buffer */
-	if (img->flags & MDP_MEMORY_ID_TYPE_FB)
-		fput_light(srcp0_file, ps0_need);
 	return ret;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index efb4da6..9f29887 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -42,6 +42,9 @@
 #include <linux/vmalloc.h>
 
 #include <mach/board.h>
+#include <mach/memory.h>
+#include <mach/msm_memtypes.h>
+#include <mach/iommu_domains.h>
 
 #include "mdss_fb.h"
 #include "mdss_mdp.h"
@@ -596,37 +599,17 @@
 	size *= mfd->fb_page;
 
 	if (mfd->index == 0) {
-		struct ion_client *iclient = mdss_get_ionclient();
-
-		if (iclient) {
-			mfd->ihdl = ion_alloc(iclient, size, SZ_4K,
-					 ION_HEAP(ION_CP_MM_HEAP_ID) |
-					 ION_HEAP(ION_SF_HEAP_ID), 0);
-			if (IS_ERR_OR_NULL(mfd->ihdl)) {
-				pr_err("unable to alloc fbmem from ion (%p)\n",
-					mfd->ihdl);
-				return -ENOMEM;
-			}
-
-			virt = ion_map_kernel(iclient, mfd->ihdl);
-			ion_phys(iclient, mfd->ihdl, &phys, &size);
-
-			if (is_mdss_iommu_attached()) {
-				ion_map_iommu(iclient, mfd->ihdl,
-					      mdss_get_iommu_domain(),
-					      0, SZ_4K, 0, &mfd->iova,
-					      (unsigned long *) &size,
-					      0, 0);
-			}
-		} else {
-			virt = dma_alloc_coherent(NULL, size,
-					(dma_addr_t *) &phys, GFP_KERNEL);
-			if (!virt) {
-				pr_err("unable to alloc fbmem size=%u\n", size);
-				return -ENOMEM;
-			}
+		virt = allocate_contiguous_memory(size, MEMTYPE_EBI1, SZ_1M, 0);
+		if (!virt) {
+			pr_err("unable to alloc fbmem size=%u\n", size);
+			return -ENOMEM;
 		}
-
+		phys = memory_pool_node_paddr(virt);
+		if (is_mdss_iommu_attached()) {
+			msm_iommu_map_contig_buffer(phys,
+				mdss_get_iommu_domain(), 0, size, SZ_4K, 0,
+				&(mfd->iova));
+		}
 		pr_info("allocating %u bytes at %p (%lx phys) for fb %d\n",
 			size, virt, phys, mfd->index);
 	} else {
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 4f641cc..0f6cfe9 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1081,8 +1081,10 @@
 
 static const struct of_device_id mdss_mdp_dt_match[] = {
 	{ .compatible = "qcom,mdss_mdp",},
+	{}
 };
 MODULE_DEVICE_TABLE(of, mdss_mdp_dt_match);
+EXPORT_COMPAT("qcom,mdss_mdp");
 
 static struct platform_driver mdss_mdp_driver = {
 	.probe = mdss_mdp_probe,
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 71ff639..5e1395e 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -2,7 +2,7 @@
 #define _MSM_KGSL_H
 
 #define KGSL_VERSION_MAJOR        3
-#define KGSL_VERSION_MINOR        12
+#define KGSL_VERSION_MINOR        13
 
 /*context flags */
 #define KGSL_CONTEXT_SAVE_GMEM		0x00000001
@@ -18,6 +18,33 @@
 /* Memory allocayion flags */
 #define KGSL_MEMFLAGS_GPUREADONLY	0x01000000
 
+#define KGSL_MEMTYPE_MASK		0x0000FF00
+#define KGSL_MEMTYPE_SHIFT		8
+
+/* Memory types for which allocations are made */
+#define KGSL_MEMTYPE_OBJECTANY			0
+#define KGSL_MEMTYPE_FRAMEBUFFER		1
+#define KGSL_MEMTYPE_RENDERBUFFER		2
+#define KGSL_MEMTYPE_ARRAYBUFFER		3
+#define KGSL_MEMTYPE_ELEMENTARRAYBUFFER		4
+#define KGSL_MEMTYPE_VERTEXARRAYBUFFER		5
+#define KGSL_MEMTYPE_TEXTURE			6
+#define KGSL_MEMTYPE_SURFACE			7
+#define KGSL_MEMTYPE_EGL_SURFACE		8
+#define KGSL_MEMTYPE_GL				9
+#define KGSL_MEMTYPE_CL				10
+#define KGSL_MEMTYPE_CL_BUFFER_MAP		11
+#define KGSL_MEMTYPE_CL_BUFFER_NOMAP		12
+#define KGSL_MEMTYPE_CL_IMAGE_MAP		13
+#define KGSL_MEMTYPE_CL_IMAGE_NOMAP		14
+#define KGSL_MEMTYPE_CL_KERNEL_STACK		15
+#define KGSL_MEMTYPE_COMMAND			16
+#define KGSL_MEMTYPE_2D				17
+#define KGSL_MEMTYPE_EGL_IMAGE			18
+#define KGSL_MEMTYPE_EGL_SHADOW			19
+#define KGSL_MEMTYPE_MULTISAMPLE		20
+#define KGSL_MEMTYPE_KERNEL			255
+
 /* generic flag values */
 #define KGSL_FLAGS_NORMALMODE  0x00000000
 #define KGSL_FLAGS_SAFEMODE    0x00000001
@@ -278,8 +305,7 @@
 	unsigned int offset;
 	unsigned int hostptr;   /*input param */
 	enum kgsl_user_mem_type memtype;
-	unsigned int reserved;	/* May be required to add
-				params for another mem type */
+	unsigned int flags;
 };
 
 #define IOCTL_KGSL_MAP_USER_MEM \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2c9509d..1f13da3 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -142,6 +142,8 @@
 extern unsigned long nr_iowait_cpu(int cpu);
 extern unsigned long this_cpu_load(void);
 
+extern void sched_update_nr_prod(int cpu, unsigned long nr, bool inc);
+extern void sched_get_nr_running_avg(int *avg, int *iowait_avg);
 
 extern void calc_global_load(unsigned long ticks);
 
diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
index 9a7dd35..3ede7d9 100644
--- a/kernel/sched/Makefile
+++ b/kernel/sched/Makefile
@@ -11,7 +11,7 @@
 CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer
 endif
 
-obj-y += core.o clock.o idle_task.o fair.o rt.o stop_task.o
+obj-y += core.o clock.o idle_task.o fair.o rt.o stop_task.o sched_avg.o
 obj-$(CONFIG_SMP) += cpupri.o
 obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
 obj-$(CONFIG_SCHEDSTATS) += stats.o
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index fb3acba..451bd4f 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -916,11 +916,13 @@
 
 static inline void inc_nr_running(struct rq *rq)
 {
+	sched_update_nr_prod(cpu_of(rq), rq->nr_running, true);
 	rq->nr_running++;
 }
 
 static inline void dec_nr_running(struct rq *rq)
 {
+	sched_update_nr_prod(cpu_of(rq), rq->nr_running, false);
 	rq->nr_running--;
 }
 
diff --git a/kernel/sched/sched_avg.c b/kernel/sched/sched_avg.c
new file mode 100644
index 0000000..8eaf2f7
--- /dev/null
+++ b/kernel/sched/sched_avg.c
@@ -0,0 +1,106 @@
+/* Copyright (c) 2012, 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.
+ */
+
+/*
+ * Scheduler hook for average runqueue determination
+ */
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/hrtimer.h>
+#include <linux/sched.h>
+#include <linux/math64.h>
+
+static DEFINE_PER_CPU(u64, nr_prod_sum);
+static DEFINE_PER_CPU(u64, last_time);
+static DEFINE_PER_CPU(u64, nr);
+static DEFINE_PER_CPU(unsigned long, iowait_prod_sum);
+static DEFINE_PER_CPU(spinlock_t, nr_lock) = __SPIN_LOCK_UNLOCKED(nr_lock);
+static s64 last_get_time;
+
+/**
+ * sched_get_nr_running_avg
+ * @return: Average nr_running and iowait value since last poll.
+ *	    Returns the avg * 100 to return up to two decimal points
+ *	    of accuracy.
+ *
+ * Obtains the average nr_running value since the last poll.
+ * This function may not be called concurrently with itself
+ */
+void sched_get_nr_running_avg(int *avg, int *iowait_avg)
+{
+	int cpu;
+	u64 curr_time = sched_clock();
+	u64 diff = curr_time - last_get_time;
+	u64 tmp_avg = 0, tmp_iowait = 0;
+
+	*avg = 0;
+	*iowait_avg = 0;
+
+	if (!diff)
+		return;
+
+	last_get_time = curr_time;
+	/* read and reset nr_running counts */
+	for_each_possible_cpu(cpu) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&per_cpu(nr_lock, cpu), flags);
+		tmp_avg += per_cpu(nr_prod_sum, cpu);
+		tmp_avg += per_cpu(nr, cpu) *
+			(curr_time - per_cpu(last_time, cpu));
+		tmp_iowait = per_cpu(iowait_prod_sum, cpu);
+		tmp_iowait +=  nr_iowait_cpu(cpu) *
+			(curr_time - per_cpu(last_time, cpu));
+		per_cpu(last_time, cpu) = curr_time;
+		per_cpu(nr_prod_sum, cpu) = 0;
+		per_cpu(iowait_prod_sum, cpu) = 0;
+		spin_unlock_irqrestore(&per_cpu(nr_lock, cpu), flags);
+	}
+
+	*avg = (int)div64_u64(tmp_avg * 100, diff);
+	*iowait_avg = (int)div64_u64(tmp_iowait * 100, diff);
+
+	BUG_ON(*avg < 0);
+	pr_debug("%s - avg:%d\n", __func__, *avg);
+	BUG_ON(*iowait_avg < 0);
+	pr_debug("%s - avg:%d\n", __func__, *iowait_avg);
+}
+EXPORT_SYMBOL(sched_get_nr_running_avg);
+
+/**
+ * sched_update_nr_prod
+ * @cpu: The core id of the nr running driver.
+ * @nr: Updated nr running value for cpu.
+ * @inc: Whether we are increasing or decreasing the count
+ * @return: N/A
+ *
+ * Update average with latest nr_running value for CPU
+ */
+void sched_update_nr_prod(int cpu, unsigned long nr_running, bool inc)
+{
+	int diff;
+	s64 curr_time;
+	unsigned long flags;
+
+	spin_lock_irqsave(&per_cpu(nr_lock, cpu), flags);
+	curr_time = sched_clock();
+	diff = curr_time - per_cpu(last_time, cpu);
+	per_cpu(last_time, cpu) = curr_time;
+	per_cpu(nr, cpu) = nr_running + (inc ? 1 : -1);
+
+	BUG_ON(per_cpu(nr, cpu) < 0);
+
+	per_cpu(nr_prod_sum, cpu) += nr_running * diff;
+	per_cpu(iowait_prod_sum, cpu) += nr_iowait_cpu(cpu) * diff;
+	spin_unlock_irqrestore(&per_cpu(nr_lock, cpu), flags);
+}
+EXPORT_SYMBOL(sched_update_nr_prod);
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 9432a06..b303878 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -4976,6 +4976,7 @@
 	SITAR_REG_VAL(SITAR_A_CDC_RX1_B6_CTL, 0x80),
 
 	SITAR_REG_VAL(SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL, 0x1B),
+	SITAR_REG_VAL(SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL, 0x5B),
 
 };